blob: eee2f9264fc8c8c0b552c5220c48721165855c28 [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?
91 if (Visiting.count(GV))
92 report_fatal_error("Circular dependency found in global variable set");
93
94 // Start visiting this global
95 Visiting.insert(GV);
96
97 // Make sure we visit all dependents first
Justin Holewinski01f89f02013-05-20 12:13:32 +000098 DenseSet<const GlobalVariable *> Others;
Justin Holewinski2c5ac702012-11-16 21:03:51 +000099 for (unsigned i = 0, e = GV->getNumOperands(); i != e; ++i)
100 DiscoverDependentGlobals(GV->getOperand(i), Others);
Justin Holewinski0497ab12013-03-30 14:29:21 +0000101
Justin Holewinski01f89f02013-05-20 12:13:32 +0000102 for (DenseSet<const GlobalVariable *>::iterator I = Others.begin(),
103 E = Others.end();
Justin Holewinski0497ab12013-03-30 14:29:21 +0000104 I != E; ++I)
Justin Holewinski2c5ac702012-11-16 21:03:51 +0000105 VisitGlobalVariableForEmission(*I, Order, Visited, Visiting);
106
107 // Now we can visit ourself
108 Order.push_back(GV);
109 Visited.insert(GV);
110 Visiting.erase(GV);
111}
112}
Justin Holewinskiae556d32012-05-04 20:18:50 +0000113
114// @TODO: This is a copy from AsmPrinter.cpp. The function is static, so we
115// cannot just link to the existing version.
116/// LowerConstant - Lower the specified LLVM Constant to an MCExpr.
117///
118using namespace nvptx;
119const MCExpr *nvptx::LowerConstant(const Constant *CV, AsmPrinter &AP) {
120 MCContext &Ctx = AP.OutContext;
121
122 if (CV->isNullValue() || isa<UndefValue>(CV))
123 return MCConstantExpr::Create(0, Ctx);
124
125 if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV))
126 return MCConstantExpr::Create(CI->getZExtValue(), Ctx);
127
128 if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
Rafael Espindola79858aa2013-10-29 17:07:16 +0000129 return MCSymbolRefExpr::Create(AP.getSymbol(GV), Ctx);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000130
131 if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV))
132 return MCSymbolRefExpr::Create(AP.GetBlockAddressSymbol(BA), Ctx);
133
134 const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV);
Craig Topper062a2ba2014-04-25 05:30:21 +0000135 if (!CE)
Justin Holewinskiae556d32012-05-04 20:18:50 +0000136 llvm_unreachable("Unknown constant value to lower!");
137
Justin Holewinskiae556d32012-05-04 20:18:50 +0000138 switch (CE->getOpcode()) {
139 default:
140 // If the code isn't optimized, there may be outstanding folding
Micah Villmowcdfe20b2012-10-08 16:38:25 +0000141 // opportunities. Attempt to fold the expression using DataLayout as a
Justin Holewinskiae556d32012-05-04 20:18:50 +0000142 // last resort before giving up.
Justin Holewinski0497ab12013-03-30 14:29:21 +0000143 if (Constant *C = ConstantFoldConstantExpression(CE, AP.TM.getDataLayout()))
Justin Holewinskiae556d32012-05-04 20:18:50 +0000144 if (C != CE)
145 return LowerConstant(C, AP);
146
147 // Otherwise report the problem to the user.
148 {
Alp Toker61471732014-06-26 00:00:48 +0000149 string_ostream OS;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000150 OS << "Unsupported expression in static initializer: ";
Chandler Carruthd48cdbf2014-01-09 02:29:41 +0000151 CE->printAsOperand(OS, /*PrintType=*/ false,
Craig Topper062a2ba2014-04-25 05:30:21 +0000152 !AP.MF ? nullptr : AP.MF->getFunction()->getParent());
Justin Holewinski0497ab12013-03-30 14:29:21 +0000153 report_fatal_error(OS.str());
Justin Holewinskiae556d32012-05-04 20:18:50 +0000154 }
Justin Holewinski9d852a82014-04-09 15:39:11 +0000155 case Instruction::AddrSpaceCast: {
156 // Strip any addrspace(1)->addrspace(0) addrspace casts. These will be
157 // handled by the generic() logic in the MCExpr printer
158 PointerType *DstTy = cast<PointerType>(CE->getType());
159 PointerType *SrcTy = cast<PointerType>(CE->getOperand(0)->getType());
160 if (SrcTy->getAddressSpace() == 1 && DstTy->getAddressSpace() == 0) {
161 return LowerConstant(cast<const Constant>(CE->getOperand(0)), AP);
162 }
163 std::string S;
164 raw_string_ostream OS(S);
165 OS << "Unsupported expression in static initializer: ";
166 CE->printAsOperand(OS, /*PrintType=*/ false,
Craig Topper062a2ba2014-04-25 05:30:21 +0000167 !AP.MF ? nullptr : AP.MF->getFunction()->getParent());
Justin Holewinski9d852a82014-04-09 15:39:11 +0000168 report_fatal_error(OS.str());
169 }
Justin Holewinskiae556d32012-05-04 20:18:50 +0000170 case Instruction::GetElementPtr: {
Micah Villmowcdfe20b2012-10-08 16:38:25 +0000171 const DataLayout &TD = *AP.TM.getDataLayout();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000172 // Generate a symbolic expression for the byte address
Nuno Lopesb6ad9822012-12-30 16:25:48 +0000173 APInt OffsetAI(TD.getPointerSizeInBits(), 0);
174 cast<GEPOperator>(CE)->accumulateConstantOffset(TD, OffsetAI);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000175
176 const MCExpr *Base = LowerConstant(CE->getOperand(0), AP);
Nuno Lopesb6ad9822012-12-30 16:25:48 +0000177 if (!OffsetAI)
Justin Holewinskiae556d32012-05-04 20:18:50 +0000178 return Base;
179
Nuno Lopesb6ad9822012-12-30 16:25:48 +0000180 int64_t Offset = OffsetAI.getSExtValue();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000181 return MCBinaryExpr::CreateAdd(Base, MCConstantExpr::Create(Offset, Ctx),
182 Ctx);
183 }
184
185 case Instruction::Trunc:
186 // We emit the value and depend on the assembler to truncate the generated
187 // expression properly. This is important for differences between
188 // blockaddress labels. Since the two labels are in the same function, it
189 // is reasonable to treat their delta as a 32-bit value.
Justin Holewinski0497ab12013-03-30 14:29:21 +0000190 // FALL THROUGH.
Justin Holewinskiae556d32012-05-04 20:18:50 +0000191 case Instruction::BitCast:
192 return LowerConstant(CE->getOperand(0), AP);
193
194 case Instruction::IntToPtr: {
Micah Villmowcdfe20b2012-10-08 16:38:25 +0000195 const DataLayout &TD = *AP.TM.getDataLayout();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000196 // Handle casts to pointers by changing them into casts to the appropriate
197 // integer type. This promotes constant folding and simplifies this code.
198 Constant *Op = CE->getOperand(0);
Chandler Carruth7ec50852012-11-01 08:07:29 +0000199 Op = ConstantExpr::getIntegerCast(Op, TD.getIntPtrType(CV->getContext()),
Justin Holewinski0497ab12013-03-30 14:29:21 +0000200 false /*ZExt*/);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000201 return LowerConstant(Op, AP);
202 }
203
204 case Instruction::PtrToInt: {
Micah Villmowcdfe20b2012-10-08 16:38:25 +0000205 const DataLayout &TD = *AP.TM.getDataLayout();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000206 // Support only foldable casts to/from pointers that can be eliminated by
207 // changing the pointer to the appropriately sized integer type.
208 Constant *Op = CE->getOperand(0);
209 Type *Ty = CE->getType();
210
211 const MCExpr *OpExpr = LowerConstant(Op, AP);
212
213 // We can emit the pointer value into this slot if the slot is an
214 // integer slot equal to the size of the pointer.
215 if (TD.getTypeAllocSize(Ty) == TD.getTypeAllocSize(Op->getType()))
216 return OpExpr;
217
218 // Otherwise the pointer is smaller than the resultant integer, mask off
219 // the high bits so we are sure to get a proper truncation if the input is
220 // a constant expr.
221 unsigned InBits = TD.getTypeAllocSizeInBits(Op->getType());
Justin Holewinski0497ab12013-03-30 14:29:21 +0000222 const MCExpr *MaskExpr =
223 MCConstantExpr::Create(~0ULL >> (64 - InBits), Ctx);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000224 return MCBinaryExpr::CreateAnd(OpExpr, MaskExpr, Ctx);
225 }
226
Justin Holewinski0497ab12013-03-30 14:29:21 +0000227 // The MC library also has a right-shift operator, but it isn't consistently
Justin Holewinskiae556d32012-05-04 20:18:50 +0000228 // signed or unsigned between different targets.
229 case Instruction::Add:
230 case Instruction::Sub:
231 case Instruction::Mul:
232 case Instruction::SDiv:
233 case Instruction::SRem:
234 case Instruction::Shl:
235 case Instruction::And:
236 case Instruction::Or:
237 case Instruction::Xor: {
238 const MCExpr *LHS = LowerConstant(CE->getOperand(0), AP);
239 const MCExpr *RHS = LowerConstant(CE->getOperand(1), AP);
240 switch (CE->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000241 default:
242 llvm_unreachable("Unknown binary operator constant cast expr");
243 case Instruction::Add:
244 return MCBinaryExpr::CreateAdd(LHS, RHS, Ctx);
245 case Instruction::Sub:
246 return MCBinaryExpr::CreateSub(LHS, RHS, Ctx);
247 case Instruction::Mul:
248 return MCBinaryExpr::CreateMul(LHS, RHS, Ctx);
249 case Instruction::SDiv:
250 return MCBinaryExpr::CreateDiv(LHS, RHS, Ctx);
251 case Instruction::SRem:
252 return MCBinaryExpr::CreateMod(LHS, RHS, Ctx);
253 case Instruction::Shl:
254 return MCBinaryExpr::CreateShl(LHS, RHS, Ctx);
255 case Instruction::And:
256 return MCBinaryExpr::CreateAnd(LHS, RHS, Ctx);
257 case Instruction::Or:
258 return MCBinaryExpr::CreateOr(LHS, RHS, Ctx);
259 case Instruction::Xor:
260 return MCBinaryExpr::CreateXor(LHS, RHS, Ctx);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000261 }
262 }
263 }
264}
265
Justin Holewinski0497ab12013-03-30 14:29:21 +0000266void NVPTXAsmPrinter::emitLineNumberAsDotLoc(const MachineInstr &MI) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000267 if (!EmitLineNumbers)
268 return;
269 if (ignoreLoc(MI))
270 return;
271
272 DebugLoc curLoc = MI.getDebugLoc();
273
274 if (prevDebugLoc.isUnknown() && curLoc.isUnknown())
275 return;
276
277 if (prevDebugLoc == curLoc)
278 return;
279
280 prevDebugLoc = curLoc;
281
282 if (curLoc.isUnknown())
283 return;
284
Justin Holewinskiae556d32012-05-04 20:18:50 +0000285 const MachineFunction *MF = MI.getParent()->getParent();
286 //const TargetMachine &TM = MF->getTarget();
287
288 const LLVMContext &ctx = MF->getFunction()->getContext();
289 DIScope Scope(curLoc.getScope(ctx));
290
Manman Ren983a16c2013-06-28 05:43:10 +0000291 assert((!Scope || Scope.isScope()) &&
292 "Scope of a DebugLoc should be null or a DIScope.");
293 if (!Scope)
294 return;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000295
296 StringRef fileName(Scope.getFilename());
297 StringRef dirName(Scope.getDirectory());
298 SmallString<128> FullPathName = dirName;
299 if (!dirName.empty() && !sys::path::is_absolute(fileName)) {
300 sys::path::append(FullPathName, fileName);
301 fileName = FullPathName.str();
302 }
303
304 if (filenameMap.find(fileName.str()) == filenameMap.end())
305 return;
306
Justin Holewinskiae556d32012-05-04 20:18:50 +0000307 // Emit the line from the source file.
Benjamin Kramer7ad41002013-10-27 11:31:46 +0000308 if (InterleaveSrc)
Justin Holewinskiae556d32012-05-04 20:18:50 +0000309 this->emitSrcInText(fileName.str(), curLoc.getLine());
310
311 std::stringstream temp;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000312 temp << "\t.loc " << filenameMap[fileName.str()] << " " << curLoc.getLine()
313 << " " << curLoc.getCol();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000314 OutStreamer.EmitRawText(Twine(temp.str().c_str()));
315}
316
317void NVPTXAsmPrinter::EmitInstruction(const MachineInstr *MI) {
318 SmallString<128> Str;
319 raw_svector_ostream OS(Str);
320 if (nvptxSubtarget.getDrvInterface() == NVPTX::CUDA)
321 emitLineNumberAsDotLoc(*MI);
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000322
323 MCInst Inst;
324 lowerToMCInst(MI, Inst);
David Woodhousee6c13e42014-01-28 23:12:42 +0000325 EmitToStreamer(OutStreamer, Inst);
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000326}
327
Justin Holewinski30d56a72014-04-09 15:39:15 +0000328// Handle symbol backtracking for targets that do not support image handles
329bool NVPTXAsmPrinter::lowerImageHandleOperand(const MachineInstr *MI,
330 unsigned OpNo, MCOperand &MCOp) {
331 const MachineOperand &MO = MI->getOperand(OpNo);
332
333 switch (MI->getOpcode()) {
334 default: return false;
335 case NVPTX::TEX_1D_F32_I32:
336 case NVPTX::TEX_1D_F32_F32:
337 case NVPTX::TEX_1D_F32_F32_LEVEL:
338 case NVPTX::TEX_1D_F32_F32_GRAD:
339 case NVPTX::TEX_1D_I32_I32:
340 case NVPTX::TEX_1D_I32_F32:
341 case NVPTX::TEX_1D_I32_F32_LEVEL:
342 case NVPTX::TEX_1D_I32_F32_GRAD:
343 case NVPTX::TEX_1D_ARRAY_F32_I32:
344 case NVPTX::TEX_1D_ARRAY_F32_F32:
345 case NVPTX::TEX_1D_ARRAY_F32_F32_LEVEL:
346 case NVPTX::TEX_1D_ARRAY_F32_F32_GRAD:
347 case NVPTX::TEX_1D_ARRAY_I32_I32:
348 case NVPTX::TEX_1D_ARRAY_I32_F32:
349 case NVPTX::TEX_1D_ARRAY_I32_F32_LEVEL:
350 case NVPTX::TEX_1D_ARRAY_I32_F32_GRAD:
351 case NVPTX::TEX_2D_F32_I32:
352 case NVPTX::TEX_2D_F32_F32:
353 case NVPTX::TEX_2D_F32_F32_LEVEL:
354 case NVPTX::TEX_2D_F32_F32_GRAD:
355 case NVPTX::TEX_2D_I32_I32:
356 case NVPTX::TEX_2D_I32_F32:
357 case NVPTX::TEX_2D_I32_F32_LEVEL:
358 case NVPTX::TEX_2D_I32_F32_GRAD:
359 case NVPTX::TEX_2D_ARRAY_F32_I32:
360 case NVPTX::TEX_2D_ARRAY_F32_F32:
361 case NVPTX::TEX_2D_ARRAY_F32_F32_LEVEL:
362 case NVPTX::TEX_2D_ARRAY_F32_F32_GRAD:
363 case NVPTX::TEX_2D_ARRAY_I32_I32:
364 case NVPTX::TEX_2D_ARRAY_I32_F32:
365 case NVPTX::TEX_2D_ARRAY_I32_F32_LEVEL:
366 case NVPTX::TEX_2D_ARRAY_I32_F32_GRAD:
367 case NVPTX::TEX_3D_F32_I32:
368 case NVPTX::TEX_3D_F32_F32:
369 case NVPTX::TEX_3D_F32_F32_LEVEL:
370 case NVPTX::TEX_3D_F32_F32_GRAD:
371 case NVPTX::TEX_3D_I32_I32:
372 case NVPTX::TEX_3D_I32_F32:
373 case NVPTX::TEX_3D_I32_F32_LEVEL:
374 case NVPTX::TEX_3D_I32_F32_GRAD:
375 {
376 // This is a texture fetch, so operand 4 is a texref and operand 5 is
377 // a samplerref
378 if (OpNo == 4) {
379 lowerImageHandleSymbol(MO.getImm(), MCOp);
380 return true;
381 }
382 if (OpNo == 5) {
383 lowerImageHandleSymbol(MO.getImm(), MCOp);
384 return true;
385 }
386
387 return false;
388 }
389 case NVPTX::SULD_1D_I8_TRAP:
390 case NVPTX::SULD_1D_I16_TRAP:
391 case NVPTX::SULD_1D_I32_TRAP:
392 case NVPTX::SULD_1D_ARRAY_I8_TRAP:
393 case NVPTX::SULD_1D_ARRAY_I16_TRAP:
394 case NVPTX::SULD_1D_ARRAY_I32_TRAP:
395 case NVPTX::SULD_2D_I8_TRAP:
396 case NVPTX::SULD_2D_I16_TRAP:
397 case NVPTX::SULD_2D_I32_TRAP:
398 case NVPTX::SULD_2D_ARRAY_I8_TRAP:
399 case NVPTX::SULD_2D_ARRAY_I16_TRAP:
400 case NVPTX::SULD_2D_ARRAY_I32_TRAP:
401 case NVPTX::SULD_3D_I8_TRAP:
402 case NVPTX::SULD_3D_I16_TRAP:
403 case NVPTX::SULD_3D_I32_TRAP: {
404 // This is a V1 surface load, so operand 1 is a surfref
405 if (OpNo == 1) {
406 lowerImageHandleSymbol(MO.getImm(), MCOp);
407 return true;
408 }
409
410 return false;
411 }
412 case NVPTX::SULD_1D_V2I8_TRAP:
413 case NVPTX::SULD_1D_V2I16_TRAP:
414 case NVPTX::SULD_1D_V2I32_TRAP:
415 case NVPTX::SULD_1D_ARRAY_V2I8_TRAP:
416 case NVPTX::SULD_1D_ARRAY_V2I16_TRAP:
417 case NVPTX::SULD_1D_ARRAY_V2I32_TRAP:
418 case NVPTX::SULD_2D_V2I8_TRAP:
419 case NVPTX::SULD_2D_V2I16_TRAP:
420 case NVPTX::SULD_2D_V2I32_TRAP:
421 case NVPTX::SULD_2D_ARRAY_V2I8_TRAP:
422 case NVPTX::SULD_2D_ARRAY_V2I16_TRAP:
423 case NVPTX::SULD_2D_ARRAY_V2I32_TRAP:
424 case NVPTX::SULD_3D_V2I8_TRAP:
425 case NVPTX::SULD_3D_V2I16_TRAP:
426 case NVPTX::SULD_3D_V2I32_TRAP: {
427 // This is a V2 surface load, so operand 2 is a surfref
428 if (OpNo == 2) {
429 lowerImageHandleSymbol(MO.getImm(), MCOp);
430 return true;
431 }
432
433 return false;
434 }
435 case NVPTX::SULD_1D_V4I8_TRAP:
436 case NVPTX::SULD_1D_V4I16_TRAP:
437 case NVPTX::SULD_1D_V4I32_TRAP:
438 case NVPTX::SULD_1D_ARRAY_V4I8_TRAP:
439 case NVPTX::SULD_1D_ARRAY_V4I16_TRAP:
440 case NVPTX::SULD_1D_ARRAY_V4I32_TRAP:
441 case NVPTX::SULD_2D_V4I8_TRAP:
442 case NVPTX::SULD_2D_V4I16_TRAP:
443 case NVPTX::SULD_2D_V4I32_TRAP:
444 case NVPTX::SULD_2D_ARRAY_V4I8_TRAP:
445 case NVPTX::SULD_2D_ARRAY_V4I16_TRAP:
446 case NVPTX::SULD_2D_ARRAY_V4I32_TRAP:
447 case NVPTX::SULD_3D_V4I8_TRAP:
448 case NVPTX::SULD_3D_V4I16_TRAP:
449 case NVPTX::SULD_3D_V4I32_TRAP: {
450 // This is a V4 surface load, so operand 4 is a surfref
451 if (OpNo == 4) {
452 lowerImageHandleSymbol(MO.getImm(), MCOp);
453 return true;
454 }
455
456 return false;
457 }
458 case NVPTX::SUST_B_1D_B8_TRAP:
459 case NVPTX::SUST_B_1D_B16_TRAP:
460 case NVPTX::SUST_B_1D_B32_TRAP:
461 case NVPTX::SUST_B_1D_V2B8_TRAP:
462 case NVPTX::SUST_B_1D_V2B16_TRAP:
463 case NVPTX::SUST_B_1D_V2B32_TRAP:
464 case NVPTX::SUST_B_1D_V4B8_TRAP:
465 case NVPTX::SUST_B_1D_V4B16_TRAP:
466 case NVPTX::SUST_B_1D_V4B32_TRAP:
467 case NVPTX::SUST_B_1D_ARRAY_B8_TRAP:
468 case NVPTX::SUST_B_1D_ARRAY_B16_TRAP:
469 case NVPTX::SUST_B_1D_ARRAY_B32_TRAP:
470 case NVPTX::SUST_B_1D_ARRAY_V2B8_TRAP:
471 case NVPTX::SUST_B_1D_ARRAY_V2B16_TRAP:
472 case NVPTX::SUST_B_1D_ARRAY_V2B32_TRAP:
473 case NVPTX::SUST_B_1D_ARRAY_V4B8_TRAP:
474 case NVPTX::SUST_B_1D_ARRAY_V4B16_TRAP:
475 case NVPTX::SUST_B_1D_ARRAY_V4B32_TRAP:
476 case NVPTX::SUST_B_2D_B8_TRAP:
477 case NVPTX::SUST_B_2D_B16_TRAP:
478 case NVPTX::SUST_B_2D_B32_TRAP:
479 case NVPTX::SUST_B_2D_V2B8_TRAP:
480 case NVPTX::SUST_B_2D_V2B16_TRAP:
481 case NVPTX::SUST_B_2D_V2B32_TRAP:
482 case NVPTX::SUST_B_2D_V4B8_TRAP:
483 case NVPTX::SUST_B_2D_V4B16_TRAP:
484 case NVPTX::SUST_B_2D_V4B32_TRAP:
485 case NVPTX::SUST_B_2D_ARRAY_B8_TRAP:
486 case NVPTX::SUST_B_2D_ARRAY_B16_TRAP:
487 case NVPTX::SUST_B_2D_ARRAY_B32_TRAP:
488 case NVPTX::SUST_B_2D_ARRAY_V2B8_TRAP:
489 case NVPTX::SUST_B_2D_ARRAY_V2B16_TRAP:
490 case NVPTX::SUST_B_2D_ARRAY_V2B32_TRAP:
491 case NVPTX::SUST_B_2D_ARRAY_V4B8_TRAP:
492 case NVPTX::SUST_B_2D_ARRAY_V4B16_TRAP:
493 case NVPTX::SUST_B_2D_ARRAY_V4B32_TRAP:
494 case NVPTX::SUST_B_3D_B8_TRAP:
495 case NVPTX::SUST_B_3D_B16_TRAP:
496 case NVPTX::SUST_B_3D_B32_TRAP:
497 case NVPTX::SUST_B_3D_V2B8_TRAP:
498 case NVPTX::SUST_B_3D_V2B16_TRAP:
499 case NVPTX::SUST_B_3D_V2B32_TRAP:
500 case NVPTX::SUST_B_3D_V4B8_TRAP:
501 case NVPTX::SUST_B_3D_V4B16_TRAP:
502 case NVPTX::SUST_B_3D_V4B32_TRAP:
503 case NVPTX::SUST_P_1D_B8_TRAP:
504 case NVPTX::SUST_P_1D_B16_TRAP:
505 case NVPTX::SUST_P_1D_B32_TRAP:
506 case NVPTX::SUST_P_1D_V2B8_TRAP:
507 case NVPTX::SUST_P_1D_V2B16_TRAP:
508 case NVPTX::SUST_P_1D_V2B32_TRAP:
509 case NVPTX::SUST_P_1D_V4B8_TRAP:
510 case NVPTX::SUST_P_1D_V4B16_TRAP:
511 case NVPTX::SUST_P_1D_V4B32_TRAP:
512 case NVPTX::SUST_P_1D_ARRAY_B8_TRAP:
513 case NVPTX::SUST_P_1D_ARRAY_B16_TRAP:
514 case NVPTX::SUST_P_1D_ARRAY_B32_TRAP:
515 case NVPTX::SUST_P_1D_ARRAY_V2B8_TRAP:
516 case NVPTX::SUST_P_1D_ARRAY_V2B16_TRAP:
517 case NVPTX::SUST_P_1D_ARRAY_V2B32_TRAP:
518 case NVPTX::SUST_P_1D_ARRAY_V4B8_TRAP:
519 case NVPTX::SUST_P_1D_ARRAY_V4B16_TRAP:
520 case NVPTX::SUST_P_1D_ARRAY_V4B32_TRAP:
521 case NVPTX::SUST_P_2D_B8_TRAP:
522 case NVPTX::SUST_P_2D_B16_TRAP:
523 case NVPTX::SUST_P_2D_B32_TRAP:
524 case NVPTX::SUST_P_2D_V2B8_TRAP:
525 case NVPTX::SUST_P_2D_V2B16_TRAP:
526 case NVPTX::SUST_P_2D_V2B32_TRAP:
527 case NVPTX::SUST_P_2D_V4B8_TRAP:
528 case NVPTX::SUST_P_2D_V4B16_TRAP:
529 case NVPTX::SUST_P_2D_V4B32_TRAP:
530 case NVPTX::SUST_P_2D_ARRAY_B8_TRAP:
531 case NVPTX::SUST_P_2D_ARRAY_B16_TRAP:
532 case NVPTX::SUST_P_2D_ARRAY_B32_TRAP:
533 case NVPTX::SUST_P_2D_ARRAY_V2B8_TRAP:
534 case NVPTX::SUST_P_2D_ARRAY_V2B16_TRAP:
535 case NVPTX::SUST_P_2D_ARRAY_V2B32_TRAP:
536 case NVPTX::SUST_P_2D_ARRAY_V4B8_TRAP:
537 case NVPTX::SUST_P_2D_ARRAY_V4B16_TRAP:
538 case NVPTX::SUST_P_2D_ARRAY_V4B32_TRAP:
539 case NVPTX::SUST_P_3D_B8_TRAP:
540 case NVPTX::SUST_P_3D_B16_TRAP:
541 case NVPTX::SUST_P_3D_B32_TRAP:
542 case NVPTX::SUST_P_3D_V2B8_TRAP:
543 case NVPTX::SUST_P_3D_V2B16_TRAP:
544 case NVPTX::SUST_P_3D_V2B32_TRAP:
545 case NVPTX::SUST_P_3D_V4B8_TRAP:
546 case NVPTX::SUST_P_3D_V4B16_TRAP:
547 case NVPTX::SUST_P_3D_V4B32_TRAP: {
548 // This is a surface store, so operand 0 is a surfref
549 if (OpNo == 0) {
550 lowerImageHandleSymbol(MO.getImm(), MCOp);
551 return true;
552 }
553
554 return false;
555 }
556 case NVPTX::TXQ_CHANNEL_ORDER:
557 case NVPTX::TXQ_CHANNEL_DATA_TYPE:
558 case NVPTX::TXQ_WIDTH:
559 case NVPTX::TXQ_HEIGHT:
560 case NVPTX::TXQ_DEPTH:
561 case NVPTX::TXQ_ARRAY_SIZE:
562 case NVPTX::TXQ_NUM_SAMPLES:
563 case NVPTX::TXQ_NUM_MIPMAP_LEVELS:
564 case NVPTX::SUQ_CHANNEL_ORDER:
565 case NVPTX::SUQ_CHANNEL_DATA_TYPE:
566 case NVPTX::SUQ_WIDTH:
567 case NVPTX::SUQ_HEIGHT:
568 case NVPTX::SUQ_DEPTH:
569 case NVPTX::SUQ_ARRAY_SIZE: {
570 // This is a query, so operand 1 is a surfref/texref
571 if (OpNo == 1) {
572 lowerImageHandleSymbol(MO.getImm(), MCOp);
573 return true;
574 }
575
576 return false;
577 }
578 }
579}
580
581void NVPTXAsmPrinter::lowerImageHandleSymbol(unsigned Index, MCOperand &MCOp) {
582 // Ewwww
583 TargetMachine &TM = const_cast<TargetMachine&>(MF->getTarget());
584 NVPTXTargetMachine &nvTM = static_cast<NVPTXTargetMachine&>(TM);
585 const NVPTXMachineFunctionInfo *MFI = MF->getInfo<NVPTXMachineFunctionInfo>();
586 const char *Sym = MFI->getImageHandleSymbol(Index);
587 std::string *SymNamePtr =
588 nvTM.getManagedStrPool()->getManagedString(Sym);
589 MCOp = GetSymbolRef(OutContext.GetOrCreateSymbol(
590 StringRef(SymNamePtr->c_str())));
591}
592
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000593void NVPTXAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
594 OutMI.setOpcode(MI->getOpcode());
Justin Holewinski30d56a72014-04-09 15:39:15 +0000595 const NVPTXSubtarget &ST = TM.getSubtarget<NVPTXSubtarget>();
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000596
Justin Holewinski3d49e5c2013-11-15 12:30:04 +0000597 // Special: Do not mangle symbol operand of CALL_PROTOTYPE
598 if (MI->getOpcode() == NVPTX::CALL_PROTOTYPE) {
599 const MachineOperand &MO = MI->getOperand(0);
Justin Holewinski30d56a72014-04-09 15:39:15 +0000600 OutMI.addOperand(GetSymbolRef(
Justin Holewinski3d49e5c2013-11-15 12:30:04 +0000601 OutContext.GetOrCreateSymbol(Twine(MO.getSymbolName()))));
602 return;
603 }
604
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000605 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
606 const MachineOperand &MO = MI->getOperand(i);
607
608 MCOperand MCOp;
Justin Holewinski30d56a72014-04-09 15:39:15 +0000609 if (!ST.hasImageHandles()) {
610 if (lowerImageHandleOperand(MI, i, MCOp)) {
611 OutMI.addOperand(MCOp);
612 continue;
613 }
614 }
615
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000616 if (lowerOperand(MO, MCOp))
617 OutMI.addOperand(MCOp);
618 }
619}
620
621bool NVPTXAsmPrinter::lowerOperand(const MachineOperand &MO,
622 MCOperand &MCOp) {
623 switch (MO.getType()) {
624 default: llvm_unreachable("unknown operand type");
625 case MachineOperand::MO_Register:
626 MCOp = MCOperand::CreateReg(encodeVirtualRegister(MO.getReg()));
627 break;
628 case MachineOperand::MO_Immediate:
629 MCOp = MCOperand::CreateImm(MO.getImm());
630 break;
631 case MachineOperand::MO_MachineBasicBlock:
632 MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
633 MO.getMBB()->getSymbol(), OutContext));
634 break;
635 case MachineOperand::MO_ExternalSymbol:
Justin Holewinski30d56a72014-04-09 15:39:15 +0000636 MCOp = GetSymbolRef(GetExternalSymbolSymbol(MO.getSymbolName()));
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000637 break;
638 case MachineOperand::MO_GlobalAddress:
Justin Holewinski30d56a72014-04-09 15:39:15 +0000639 MCOp = GetSymbolRef(getSymbol(MO.getGlobal()));
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000640 break;
641 case MachineOperand::MO_FPImmediate: {
642 const ConstantFP *Cnt = MO.getFPImm();
643 APFloat Val = Cnt->getValueAPF();
644
645 switch (Cnt->getType()->getTypeID()) {
646 default: report_fatal_error("Unsupported FP type"); break;
647 case Type::FloatTyID:
648 MCOp = MCOperand::CreateExpr(
649 NVPTXFloatMCExpr::CreateConstantFPSingle(Val, OutContext));
650 break;
651 case Type::DoubleTyID:
652 MCOp = MCOperand::CreateExpr(
653 NVPTXFloatMCExpr::CreateConstantFPDouble(Val, OutContext));
654 break;
655 }
656 break;
657 }
658 }
659 return true;
660}
661
662unsigned NVPTXAsmPrinter::encodeVirtualRegister(unsigned Reg) {
Justin Holewinski871ec932013-08-06 14:13:31 +0000663 if (TargetRegisterInfo::isVirtualRegister(Reg)) {
664 const TargetRegisterClass *RC = MRI->getRegClass(Reg);
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000665
Justin Holewinski871ec932013-08-06 14:13:31 +0000666 DenseMap<unsigned, unsigned> &RegMap = VRegMapping[RC];
667 unsigned RegNum = RegMap[Reg];
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000668
Justin Holewinski871ec932013-08-06 14:13:31 +0000669 // Encode the register class in the upper 4 bits
670 // Must be kept in sync with NVPTXInstPrinter::printRegName
671 unsigned Ret = 0;
672 if (RC == &NVPTX::Int1RegsRegClass) {
673 Ret = (1 << 28);
674 } else if (RC == &NVPTX::Int16RegsRegClass) {
675 Ret = (2 << 28);
676 } else if (RC == &NVPTX::Int32RegsRegClass) {
677 Ret = (3 << 28);
678 } else if (RC == &NVPTX::Int64RegsRegClass) {
679 Ret = (4 << 28);
680 } else if (RC == &NVPTX::Float32RegsRegClass) {
681 Ret = (5 << 28);
682 } else if (RC == &NVPTX::Float64RegsRegClass) {
683 Ret = (6 << 28);
684 } else {
685 report_fatal_error("Bad register class");
686 }
687
688 // Insert the vreg number
689 Ret |= (RegNum & 0x0FFFFFFF);
690 return Ret;
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000691 } else {
Justin Holewinski871ec932013-08-06 14:13:31 +0000692 // Some special-use registers are actually physical registers.
693 // Encode this as the register class ID of 0 and the real register ID.
694 return Reg & 0x0FFFFFFF;
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000695 }
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000696}
697
Justin Holewinski30d56a72014-04-09 15:39:15 +0000698MCOperand NVPTXAsmPrinter::GetSymbolRef(const MCSymbol *Symbol) {
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000699 const MCExpr *Expr;
Justin Holewinski8b24e1e2013-08-06 23:06:42 +0000700 Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
701 OutContext);
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000702 return MCOperand::CreateExpr(Expr);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000703}
704
Justin Holewinski0497ab12013-03-30 14:29:21 +0000705void NVPTXAsmPrinter::printReturnValStr(const Function *F, raw_ostream &O) {
Micah Villmowcdfe20b2012-10-08 16:38:25 +0000706 const DataLayout *TD = TM.getDataLayout();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000707 const TargetLowering *TLI = TM.getTargetLowering();
708
709 Type *Ty = F->getReturnType();
710
711 bool isABI = (nvptxSubtarget.getSmVersion() >= 20);
712
713 if (Ty->getTypeID() == Type::VoidTyID)
714 return;
715
716 O << " (";
717
718 if (isABI) {
Rafael Espindola08013342013-12-07 19:34:20 +0000719 if (Ty->isFloatingPointTy() || Ty->isIntegerTy()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000720 unsigned size = 0;
721 if (const IntegerType *ITy = dyn_cast<IntegerType>(Ty)) {
722 size = ITy->getBitWidth();
Justin Holewinski0497ab12013-03-30 14:29:21 +0000723 if (size < 32)
724 size = 32;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000725 } else {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000726 assert(Ty->isFloatingPointTy() && "Floating point type expected here");
Justin Holewinskiae556d32012-05-04 20:18:50 +0000727 size = Ty->getPrimitiveSizeInBits();
728 }
729
730 O << ".param .b" << size << " func_retval0";
Justin Holewinski0497ab12013-03-30 14:29:21 +0000731 } else if (isa<PointerType>(Ty)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000732 O << ".param .b" << TLI->getPointerTy().getSizeInBits()
Justin Holewinski0497ab12013-03-30 14:29:21 +0000733 << " func_retval0";
Justin Holewinskiae556d32012-05-04 20:18:50 +0000734 } else {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000735 if ((Ty->getTypeID() == Type::StructTyID) || isa<VectorType>(Ty)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000736 SmallVector<EVT, 16> vtparts;
737 ComputeValueVTs(*TLI, Ty, vtparts);
738 unsigned totalsz = 0;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000739 for (unsigned i = 0, e = vtparts.size(); i != e; ++i) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000740 unsigned elems = 1;
741 EVT elemtype = vtparts[i];
742 if (vtparts[i].isVector()) {
743 elems = vtparts[i].getVectorNumElements();
744 elemtype = vtparts[i].getVectorElementType();
745 }
Justin Holewinski0497ab12013-03-30 14:29:21 +0000746 for (unsigned j = 0, je = elems; j != je; ++j) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000747 unsigned sz = elemtype.getSizeInBits();
Justin Holewinski0497ab12013-03-30 14:29:21 +0000748 if (elemtype.isInteger() && (sz < 8))
749 sz = 8;
750 totalsz += sz / 8;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000751 }
752 }
753 unsigned retAlignment = 0;
754 if (!llvm::getAlign(*F, 0, retAlignment))
755 retAlignment = TD->getABITypeAlignment(Ty);
Justin Holewinski0497ab12013-03-30 14:29:21 +0000756 O << ".param .align " << retAlignment << " .b8 func_retval0[" << totalsz
757 << "]";
Justin Holewinskiae556d32012-05-04 20:18:50 +0000758 } else
Justin Holewinski0497ab12013-03-30 14:29:21 +0000759 assert(false && "Unknown return type");
Justin Holewinskiae556d32012-05-04 20:18:50 +0000760 }
761 } else {
762 SmallVector<EVT, 16> vtparts;
763 ComputeValueVTs(*TLI, Ty, vtparts);
764 unsigned idx = 0;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000765 for (unsigned i = 0, e = vtparts.size(); i != e; ++i) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000766 unsigned elems = 1;
767 EVT elemtype = vtparts[i];
768 if (vtparts[i].isVector()) {
769 elems = vtparts[i].getVectorNumElements();
770 elemtype = vtparts[i].getVectorElementType();
771 }
772
Justin Holewinski0497ab12013-03-30 14:29:21 +0000773 for (unsigned j = 0, je = elems; j != je; ++j) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000774 unsigned sz = elemtype.getSizeInBits();
Justin Holewinski0497ab12013-03-30 14:29:21 +0000775 if (elemtype.isInteger() && (sz < 32))
776 sz = 32;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000777 O << ".reg .b" << sz << " func_retval" << idx;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000778 if (j < je - 1)
779 O << ", ";
Justin Holewinskiae556d32012-05-04 20:18:50 +0000780 ++idx;
781 }
Justin Holewinski0497ab12013-03-30 14:29:21 +0000782 if (i < e - 1)
Justin Holewinskiae556d32012-05-04 20:18:50 +0000783 O << ", ";
784 }
785 }
786 O << ") ";
787 return;
788}
789
790void NVPTXAsmPrinter::printReturnValStr(const MachineFunction &MF,
791 raw_ostream &O) {
792 const Function *F = MF.getFunction();
793 printReturnValStr(F, O);
794}
795
796void NVPTXAsmPrinter::EmitFunctionEntryLabel() {
797 SmallString<128> Str;
798 raw_svector_ostream O(Str);
799
Justin Holewinski01f89f02013-05-20 12:13:32 +0000800 if (!GlobalsEmitted) {
801 emitGlobals(*MF->getFunction()->getParent());
802 GlobalsEmitted = true;
803 }
804
Justin Holewinskiae556d32012-05-04 20:18:50 +0000805 // Set up
806 MRI = &MF->getRegInfo();
807 F = MF->getFunction();
Justin Holewinski0497ab12013-03-30 14:29:21 +0000808 emitLinkageDirective(F, O);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000809 if (llvm::isKernelFunction(*F))
810 O << ".entry ";
811 else {
812 O << ".func ";
813 printReturnValStr(*MF, O);
814 }
815
816 O << *CurrentFnSym;
817
818 emitFunctionParamList(*MF, O);
819
820 if (llvm::isKernelFunction(*F))
821 emitKernelFunctionDirectives(*F, O);
822
823 OutStreamer.EmitRawText(O.str());
824
825 prevDebugLoc = DebugLoc();
826}
827
828void NVPTXAsmPrinter::EmitFunctionBodyStart() {
Justin Holewinskidbb3b2f2013-05-31 12:14:49 +0000829 VRegMapping.clear();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000830 OutStreamer.EmitRawText(StringRef("{\n"));
831 setAndEmitFunctionVirtualRegisters(*MF);
832
833 SmallString<128> Str;
834 raw_svector_ostream O(Str);
835 emitDemotedVars(MF->getFunction(), O);
836 OutStreamer.EmitRawText(O.str());
837}
838
839void NVPTXAsmPrinter::EmitFunctionBodyEnd() {
840 OutStreamer.EmitRawText(StringRef("}\n"));
Justin Holewinskidbb3b2f2013-05-31 12:14:49 +0000841 VRegMapping.clear();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000842}
843
Justin Holewinski660597d2013-10-11 12:39:36 +0000844void NVPTXAsmPrinter::emitImplicitDef(const MachineInstr *MI) const {
845 unsigned RegNo = MI->getOperand(0).getReg();
846 const TargetRegisterInfo *TRI = TM.getRegisterInfo();
847 if (TRI->isVirtualRegister(RegNo)) {
848 OutStreamer.AddComment(Twine("implicit-def: ") +
849 getVirtualRegisterName(RegNo));
850 } else {
851 OutStreamer.AddComment(Twine("implicit-def: ") +
852 TM.getRegisterInfo()->getName(RegNo));
853 }
854 OutStreamer.AddBlankLine();
855}
856
Justin Holewinski0497ab12013-03-30 14:29:21 +0000857void NVPTXAsmPrinter::emitKernelFunctionDirectives(const Function &F,
858 raw_ostream &O) const {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000859 // If the NVVM IR has some of reqntid* specified, then output
860 // the reqntid directive, and set the unspecified ones to 1.
861 // If none of reqntid* is specified, don't output reqntid directive.
862 unsigned reqntidx, reqntidy, reqntidz;
863 bool specified = false;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000864 if (llvm::getReqNTIDx(F, reqntidx) == false)
865 reqntidx = 1;
866 else
867 specified = true;
868 if (llvm::getReqNTIDy(F, reqntidy) == false)
869 reqntidy = 1;
870 else
871 specified = true;
872 if (llvm::getReqNTIDz(F, reqntidz) == false)
873 reqntidz = 1;
874 else
875 specified = true;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000876
877 if (specified)
Justin Holewinski0497ab12013-03-30 14:29:21 +0000878 O << ".reqntid " << reqntidx << ", " << reqntidy << ", " << reqntidz
879 << "\n";
Justin Holewinskiae556d32012-05-04 20:18:50 +0000880
881 // If the NVVM IR has some of maxntid* specified, then output
882 // the maxntid directive, and set the unspecified ones to 1.
883 // If none of maxntid* is specified, don't output maxntid directive.
884 unsigned maxntidx, maxntidy, maxntidz;
885 specified = false;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000886 if (llvm::getMaxNTIDx(F, maxntidx) == false)
887 maxntidx = 1;
888 else
889 specified = true;
890 if (llvm::getMaxNTIDy(F, maxntidy) == false)
891 maxntidy = 1;
892 else
893 specified = true;
894 if (llvm::getMaxNTIDz(F, maxntidz) == false)
895 maxntidz = 1;
896 else
897 specified = true;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000898
899 if (specified)
Justin Holewinski0497ab12013-03-30 14:29:21 +0000900 O << ".maxntid " << maxntidx << ", " << maxntidy << ", " << maxntidz
901 << "\n";
Justin Holewinskiae556d32012-05-04 20:18:50 +0000902
903 unsigned mincta;
904 if (llvm::getMinCTASm(F, mincta))
905 O << ".minnctapersm " << mincta << "\n";
906}
907
Justin Holewinski660597d2013-10-11 12:39:36 +0000908std::string
909NVPTXAsmPrinter::getVirtualRegisterName(unsigned Reg) const {
910 const TargetRegisterClass *RC = MRI->getRegClass(Reg);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000911
Justin Holewinski660597d2013-10-11 12:39:36 +0000912 std::string Name;
913 raw_string_ostream NameStr(Name);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000914
Justin Holewinski660597d2013-10-11 12:39:36 +0000915 VRegRCMap::const_iterator I = VRegMapping.find(RC);
916 assert(I != VRegMapping.end() && "Bad register class");
917 const DenseMap<unsigned, unsigned> &RegMap = I->second;
918
919 VRegMap::const_iterator VI = RegMap.find(Reg);
920 assert(VI != RegMap.end() && "Bad virtual register");
921 unsigned MappedVR = VI->second;
922
923 NameStr << getNVPTXRegClassStr(RC) << MappedVR;
924
925 NameStr.flush();
926 return Name;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000927}
928
Justin Holewinski660597d2013-10-11 12:39:36 +0000929void NVPTXAsmPrinter::emitVirtualRegister(unsigned int vr,
Justin Holewinski0497ab12013-03-30 14:29:21 +0000930 raw_ostream &O) {
Justin Holewinski660597d2013-10-11 12:39:36 +0000931 O << getVirtualRegisterName(vr);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000932}
933
Justin Holewinski0497ab12013-03-30 14:29:21 +0000934void NVPTXAsmPrinter::printVecModifiedImmediate(
935 const MachineOperand &MO, const char *Modifier, raw_ostream &O) {
936 static const char vecelem[] = { '0', '1', '2', '3', '0', '1', '2', '3' };
937 int Imm = (int) MO.getImm();
938 if (0 == strcmp(Modifier, "vecelem"))
Justin Holewinskiae556d32012-05-04 20:18:50 +0000939 O << "_" << vecelem[Imm];
Justin Holewinski0497ab12013-03-30 14:29:21 +0000940 else if (0 == strcmp(Modifier, "vecv4comm1")) {
941 if ((Imm < 0) || (Imm > 3))
Justin Holewinskiae556d32012-05-04 20:18:50 +0000942 O << "//";
Justin Holewinski0497ab12013-03-30 14:29:21 +0000943 } else if (0 == strcmp(Modifier, "vecv4comm2")) {
944 if ((Imm < 4) || (Imm > 7))
Justin Holewinskiae556d32012-05-04 20:18:50 +0000945 O << "//";
Justin Holewinski0497ab12013-03-30 14:29:21 +0000946 } else if (0 == strcmp(Modifier, "vecv4pos")) {
947 if (Imm < 0)
948 Imm = 0;
949 O << "_" << vecelem[Imm % 4];
950 } else if (0 == strcmp(Modifier, "vecv2comm1")) {
951 if ((Imm < 0) || (Imm > 1))
Justin Holewinskiae556d32012-05-04 20:18:50 +0000952 O << "//";
Justin Holewinski0497ab12013-03-30 14:29:21 +0000953 } else if (0 == strcmp(Modifier, "vecv2comm2")) {
954 if ((Imm < 2) || (Imm > 3))
Justin Holewinskiae556d32012-05-04 20:18:50 +0000955 O << "//";
Justin Holewinski0497ab12013-03-30 14:29:21 +0000956 } else if (0 == strcmp(Modifier, "vecv2pos")) {
957 if (Imm < 0)
958 Imm = 0;
959 O << "_" << vecelem[Imm % 2];
960 } else
Craig Topperbdf39a42012-05-24 07:02:50 +0000961 llvm_unreachable("Unknown Modifier on immediate operand");
Justin Holewinskiae556d32012-05-04 20:18:50 +0000962}
963
Justin Holewinskidc5e3b62013-06-28 17:58:04 +0000964
965
Justin Holewinski0497ab12013-03-30 14:29:21 +0000966void NVPTXAsmPrinter::emitDeclaration(const Function *F, raw_ostream &O) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000967
Justin Holewinski0497ab12013-03-30 14:29:21 +0000968 emitLinkageDirective(F, O);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000969 if (llvm::isKernelFunction(*F))
970 O << ".entry ";
971 else
972 O << ".func ";
973 printReturnValStr(F, O);
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +0000974 O << *getSymbol(F) << "\n";
Justin Holewinskiae556d32012-05-04 20:18:50 +0000975 emitFunctionParamList(F, O);
976 O << ";\n";
977}
978
Justin Holewinski0497ab12013-03-30 14:29:21 +0000979static bool usedInGlobalVarDef(const Constant *C) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000980 if (!C)
981 return false;
982
983 if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
984 if (GV->getName().str() == "llvm.used")
985 return false;
986 return true;
987 }
988
Chandler Carruthcdf47882014-03-09 03:16:01 +0000989 for (const User *U : C->users())
990 if (const Constant *C = dyn_cast<Constant>(U))
991 if (usedInGlobalVarDef(C))
992 return true;
993
Justin Holewinskiae556d32012-05-04 20:18:50 +0000994 return false;
995}
996
Justin Holewinski0497ab12013-03-30 14:29:21 +0000997static bool usedInOneFunc(const User *U, Function const *&oneFunc) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000998 if (const GlobalVariable *othergv = dyn_cast<GlobalVariable>(U)) {
999 if (othergv->getName().str() == "llvm.used")
1000 return true;
1001 }
1002
1003 if (const Instruction *instr = dyn_cast<Instruction>(U)) {
1004 if (instr->getParent() && instr->getParent()->getParent()) {
1005 const Function *curFunc = instr->getParent()->getParent();
1006 if (oneFunc && (curFunc != oneFunc))
1007 return false;
1008 oneFunc = curFunc;
1009 return true;
Justin Holewinski0497ab12013-03-30 14:29:21 +00001010 } else
Justin Holewinskiae556d32012-05-04 20:18:50 +00001011 return false;
1012 }
1013
1014 if (const MDNode *md = dyn_cast<MDNode>(U))
1015 if (md->hasName() && ((md->getName().str() == "llvm.dbg.gv") ||
Justin Holewinski0497ab12013-03-30 14:29:21 +00001016 (md->getName().str() == "llvm.dbg.sp")))
Justin Holewinskiae556d32012-05-04 20:18:50 +00001017 return true;
1018
Chandler Carruthcdf47882014-03-09 03:16:01 +00001019 for (const User *UU : U->users())
1020 if (usedInOneFunc(UU, oneFunc) == false)
Justin Holewinskiae556d32012-05-04 20:18:50 +00001021 return false;
Chandler Carruthcdf47882014-03-09 03:16:01 +00001022
Justin Holewinskiae556d32012-05-04 20:18:50 +00001023 return true;
1024}
1025
1026/* Find out if a global variable can be demoted to local scope.
1027 * Currently, this is valid for CUDA shared variables, which have local
1028 * scope and global lifetime. So the conditions to check are :
1029 * 1. Is the global variable in shared address space?
1030 * 2. Does it have internal linkage?
1031 * 3. Is the global variable referenced only in one function?
1032 */
1033static bool canDemoteGlobalVar(const GlobalVariable *gv, Function const *&f) {
1034 if (gv->hasInternalLinkage() == false)
1035 return false;
1036 const PointerType *Pty = gv->getType();
1037 if (Pty->getAddressSpace() != llvm::ADDRESS_SPACE_SHARED)
1038 return false;
1039
Craig Topper062a2ba2014-04-25 05:30:21 +00001040 const Function *oneFunc = nullptr;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001041
1042 bool flag = usedInOneFunc(gv, oneFunc);
1043 if (flag == false)
1044 return false;
1045 if (!oneFunc)
1046 return false;
1047 f = oneFunc;
1048 return true;
1049}
1050
1051static bool useFuncSeen(const Constant *C,
1052 llvm::DenseMap<const Function *, bool> &seenMap) {
Chandler Carruthcdf47882014-03-09 03:16:01 +00001053 for (const User *U : C->users()) {
1054 if (const Constant *cu = dyn_cast<Constant>(U)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001055 if (useFuncSeen(cu, seenMap))
1056 return true;
Chandler Carruthcdf47882014-03-09 03:16:01 +00001057 } else if (const Instruction *I = dyn_cast<Instruction>(U)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001058 const BasicBlock *bb = I->getParent();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001059 if (!bb)
1060 continue;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001061 const Function *caller = bb->getParent();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001062 if (!caller)
1063 continue;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001064 if (seenMap.find(caller) != seenMap.end())
1065 return true;
1066 }
1067 }
1068 return false;
1069}
1070
Justin Holewinski01f89f02013-05-20 12:13:32 +00001071void NVPTXAsmPrinter::emitDeclarations(const Module &M, raw_ostream &O) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001072 llvm::DenseMap<const Function *, bool> seenMap;
Justin Holewinski0497ab12013-03-30 14:29:21 +00001073 for (Module::const_iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001074 const Function *F = FI;
1075
1076 if (F->isDeclaration()) {
1077 if (F->use_empty())
1078 continue;
1079 if (F->getIntrinsicID())
1080 continue;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001081 emitDeclaration(F, O);
1082 continue;
1083 }
Chandler Carruthcdf47882014-03-09 03:16:01 +00001084 for (const User *U : F->users()) {
1085 if (const Constant *C = dyn_cast<Constant>(U)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001086 if (usedInGlobalVarDef(C)) {
1087 // The use is in the initialization of a global variable
1088 // that is a function pointer, so print a declaration
1089 // for the original function
Justin Holewinskiae556d32012-05-04 20:18:50 +00001090 emitDeclaration(F, O);
1091 break;
1092 }
1093 // Emit a declaration of this function if the function that
1094 // uses this constant expr has already been seen.
1095 if (useFuncSeen(C, seenMap)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001096 emitDeclaration(F, O);
1097 break;
1098 }
1099 }
1100
Chandler Carruthcdf47882014-03-09 03:16:01 +00001101 if (!isa<Instruction>(U))
Justin Holewinski0497ab12013-03-30 14:29:21 +00001102 continue;
Chandler Carruthcdf47882014-03-09 03:16:01 +00001103 const Instruction *instr = cast<Instruction>(U);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001104 const BasicBlock *bb = instr->getParent();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001105 if (!bb)
1106 continue;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001107 const Function *caller = bb->getParent();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001108 if (!caller)
1109 continue;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001110
1111 // If a caller has already been seen, then the caller is
1112 // appearing in the module before the callee. so print out
1113 // a declaration for the callee.
1114 if (seenMap.find(caller) != seenMap.end()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001115 emitDeclaration(F, O);
1116 break;
1117 }
1118 }
1119 seenMap[F] = true;
1120 }
1121}
1122
1123void NVPTXAsmPrinter::recordAndEmitFilenames(Module &M) {
1124 DebugInfoFinder DbgFinder;
1125 DbgFinder.processModule(M);
1126
Justin Holewinski0497ab12013-03-30 14:29:21 +00001127 unsigned i = 1;
Alon Mishnead312152014-03-18 09:41:07 +00001128 for (DICompileUnit DIUnit : DbgFinder.compile_units()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001129 StringRef Filename(DIUnit.getFilename());
1130 StringRef Dirname(DIUnit.getDirectory());
1131 SmallString<128> FullPathName = Dirname;
1132 if (!Dirname.empty() && !sys::path::is_absolute(Filename)) {
1133 sys::path::append(FullPathName, Filename);
1134 Filename = FullPathName.str();
1135 }
1136 if (filenameMap.find(Filename.str()) != filenameMap.end())
1137 continue;
1138 filenameMap[Filename.str()] = i;
1139 OutStreamer.EmitDwarfFileDirective(i, "", Filename.str());
1140 ++i;
1141 }
1142
Alon Mishnead312152014-03-18 09:41:07 +00001143 for (DISubprogram SP : DbgFinder.subprograms()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001144 StringRef Filename(SP.getFilename());
1145 StringRef Dirname(SP.getDirectory());
1146 SmallString<128> FullPathName = Dirname;
1147 if (!Dirname.empty() && !sys::path::is_absolute(Filename)) {
1148 sys::path::append(FullPathName, Filename);
1149 Filename = FullPathName.str();
1150 }
1151 if (filenameMap.find(Filename.str()) != filenameMap.end())
1152 continue;
1153 filenameMap[Filename.str()] = i;
1154 ++i;
1155 }
1156}
1157
Justin Holewinski0497ab12013-03-30 14:29:21 +00001158bool NVPTXAsmPrinter::doInitialization(Module &M) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001159
1160 SmallString<128> Str1;
1161 raw_svector_ostream OS1(Str1);
1162
1163 MMI = getAnalysisIfAvailable<MachineModuleInfo>();
1164 MMI->AnalyzeModule(M);
1165
1166 // We need to call the parent's one explicitly.
1167 //bool Result = AsmPrinter::doInitialization(M);
1168
1169 // Initialize TargetLoweringObjectFile.
Justin Holewinski0497ab12013-03-30 14:29:21 +00001170 const_cast<TargetLoweringObjectFile &>(getObjFileLowering())
1171 .Initialize(OutContext, TM);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001172
Rafael Espindola58873562014-01-03 19:21:54 +00001173 Mang = new Mangler(TM.getDataLayout());
Justin Holewinskiae556d32012-05-04 20:18:50 +00001174
1175 // Emit header before any dwarf directives are emitted below.
1176 emitHeader(M, OS1);
1177 OutStreamer.EmitRawText(OS1.str());
1178
Justin Holewinskiae556d32012-05-04 20:18:50 +00001179 // Already commented out
1180 //bool Result = AsmPrinter::doInitialization(M);
1181
Justin Holewinskid2bbdf02013-07-01 13:00:14 +00001182 // Emit module-level inline asm if it exists.
1183 if (!M.getModuleInlineAsm().empty()) {
1184 OutStreamer.AddComment("Start of file scope inline assembly");
1185 OutStreamer.AddBlankLine();
1186 OutStreamer.EmitRawText(StringRef(M.getModuleInlineAsm()));
1187 OutStreamer.AddBlankLine();
1188 OutStreamer.AddComment("End of file scope inline assembly");
1189 OutStreamer.AddBlankLine();
1190 }
1191
Justin Holewinskiae556d32012-05-04 20:18:50 +00001192 if (nvptxSubtarget.getDrvInterface() == NVPTX::CUDA)
1193 recordAndEmitFilenames(M);
1194
Justin Holewinski01f89f02013-05-20 12:13:32 +00001195 GlobalsEmitted = false;
1196
1197 return false; // success
1198}
1199
1200void NVPTXAsmPrinter::emitGlobals(const Module &M) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001201 SmallString<128> Str2;
1202 raw_svector_ostream OS2(Str2);
1203
1204 emitDeclarations(M, OS2);
1205
Justin Holewinski2c5ac702012-11-16 21:03:51 +00001206 // As ptxas does not support forward references of globals, we need to first
1207 // sort the list of module-level globals in def-use order. We visit each
1208 // global variable in order, and ensure that we emit it *after* its dependent
1209 // globals. We use a little extra memory maintaining both a set and a list to
1210 // have fast searches while maintaining a strict ordering.
Justin Holewinski01f89f02013-05-20 12:13:32 +00001211 SmallVector<const GlobalVariable *, 8> Globals;
1212 DenseSet<const GlobalVariable *> GVVisited;
1213 DenseSet<const GlobalVariable *> GVVisiting;
Justin Holewinski2c5ac702012-11-16 21:03:51 +00001214
1215 // Visit each global variable, in order
Justin Holewinski01f89f02013-05-20 12:13:32 +00001216 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
1217 I != E; ++I)
Justin Holewinski2c5ac702012-11-16 21:03:51 +00001218 VisitGlobalVariableForEmission(I, Globals, GVVisited, GVVisiting);
1219
Justin Holewinski0497ab12013-03-30 14:29:21 +00001220 assert(GVVisited.size() == M.getGlobalList().size() &&
Justin Holewinski2c5ac702012-11-16 21:03:51 +00001221 "Missed a global variable");
1222 assert(GVVisiting.size() == 0 && "Did not fully process a global variable");
1223
1224 // Print out module-level global variables in proper order
1225 for (unsigned i = 0, e = Globals.size(); i != e; ++i)
1226 printModuleLevelGV(Globals[i], OS2);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001227
1228 OS2 << '\n';
1229
1230 OutStreamer.EmitRawText(OS2.str());
Justin Holewinskiae556d32012-05-04 20:18:50 +00001231}
1232
Justin Holewinski0497ab12013-03-30 14:29:21 +00001233void NVPTXAsmPrinter::emitHeader(Module &M, raw_ostream &O) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001234 O << "//\n";
1235 O << "// Generated by LLVM NVPTX Back-End\n";
1236 O << "//\n";
1237 O << "\n";
1238
Justin Holewinski1812ee92012-11-12 03:16:43 +00001239 unsigned PTXVersion = nvptxSubtarget.getPTXVersion();
1240 O << ".version " << (PTXVersion / 10) << "." << (PTXVersion % 10) << "\n";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001241
1242 O << ".target ";
1243 O << nvptxSubtarget.getTargetName();
1244
1245 if (nvptxSubtarget.getDrvInterface() == NVPTX::NVCL)
1246 O << ", texmode_independent";
1247 if (nvptxSubtarget.getDrvInterface() == NVPTX::CUDA) {
1248 if (!nvptxSubtarget.hasDouble())
1249 O << ", map_f64_to_f32";
1250 }
1251
1252 if (MAI->doesSupportDebugInformation())
1253 O << ", debug";
1254
1255 O << "\n";
1256
1257 O << ".address_size ";
1258 if (nvptxSubtarget.is64Bit())
1259 O << "64";
1260 else
1261 O << "32";
1262 O << "\n";
1263
1264 O << "\n";
1265}
1266
1267bool NVPTXAsmPrinter::doFinalization(Module &M) {
Justin Holewinski01f89f02013-05-20 12:13:32 +00001268
1269 // If we did not emit any functions, then the global declarations have not
1270 // yet been emitted.
1271 if (!GlobalsEmitted) {
1272 emitGlobals(M);
1273 GlobalsEmitted = true;
1274 }
1275
Justin Holewinskiae556d32012-05-04 20:18:50 +00001276 // XXX Temproarily remove global variables so that doFinalization() will not
1277 // emit them again (global variables are emitted at beginning).
1278
1279 Module::GlobalListType &global_list = M.getGlobalList();
1280 int i, n = global_list.size();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001281 GlobalVariable **gv_array = new GlobalVariable *[n];
Justin Holewinskiae556d32012-05-04 20:18:50 +00001282
1283 // first, back-up GlobalVariable in gv_array
1284 i = 0;
1285 for (Module::global_iterator I = global_list.begin(), E = global_list.end();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001286 I != E; ++I)
Justin Holewinskiae556d32012-05-04 20:18:50 +00001287 gv_array[i++] = &*I;
1288
1289 // second, empty global_list
1290 while (!global_list.empty())
1291 global_list.remove(global_list.begin());
1292
1293 // call doFinalization
1294 bool ret = AsmPrinter::doFinalization(M);
1295
1296 // now we restore global variables
Justin Holewinski0497ab12013-03-30 14:29:21 +00001297 for (i = 0; i < n; i++)
Justin Holewinskiae556d32012-05-04 20:18:50 +00001298 global_list.insert(global_list.end(), gv_array[i]);
1299
Justin Holewinski59596952014-04-09 15:38:52 +00001300 clearAnnotationCache(&M);
1301
Justin Holewinskiae556d32012-05-04 20:18:50 +00001302 delete[] gv_array;
1303 return ret;
1304
Justin Holewinskiae556d32012-05-04 20:18:50 +00001305 //bool Result = AsmPrinter::doFinalization(M);
1306 // Instead of calling the parents doFinalization, we may
1307 // clone parents doFinalization and customize here.
1308 // Currently, we if NVISA out the EmitGlobals() in
1309 // parent's doFinalization, which is too intrusive.
1310 //
1311 // Same for the doInitialization.
1312 //return Result;
1313}
1314
1315// This function emits appropriate linkage directives for
1316// functions and global variables.
1317//
1318// extern function declaration -> .extern
1319// extern function definition -> .visible
1320// external global variable with init -> .visible
1321// external without init -> .extern
1322// appending -> not allowed, assert.
1323
Justin Holewinski0497ab12013-03-30 14:29:21 +00001324void NVPTXAsmPrinter::emitLinkageDirective(const GlobalValue *V,
1325 raw_ostream &O) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001326 if (nvptxSubtarget.getDrvInterface() == NVPTX::CUDA) {
1327 if (V->hasExternalLinkage()) {
1328 if (isa<GlobalVariable>(V)) {
1329 const GlobalVariable *GVar = cast<GlobalVariable>(V);
1330 if (GVar) {
1331 if (GVar->hasInitializer())
1332 O << ".visible ";
1333 else
1334 O << ".extern ";
1335 }
1336 } else if (V->isDeclaration())
1337 O << ".extern ";
1338 else
1339 O << ".visible ";
1340 } else if (V->hasAppendingLinkage()) {
1341 std::string msg;
1342 msg.append("Error: ");
1343 msg.append("Symbol ");
1344 if (V->hasName())
1345 msg.append(V->getName().str());
1346 msg.append("has unsupported appending linkage type");
1347 llvm_unreachable(msg.c_str());
1348 }
1349 }
1350}
1351
Justin Holewinski01f89f02013-05-20 12:13:32 +00001352void NVPTXAsmPrinter::printModuleLevelGV(const GlobalVariable *GVar,
1353 raw_ostream &O,
Justin Holewinskiae556d32012-05-04 20:18:50 +00001354 bool processDemoted) {
1355
1356 // Skip meta data
1357 if (GVar->hasSection()) {
Rafael Espindola64c1e182014-06-03 02:41:57 +00001358 if (GVar->getSection() == StringRef("llvm.metadata"))
Justin Holewinskiae556d32012-05-04 20:18:50 +00001359 return;
1360 }
1361
Micah Villmowcdfe20b2012-10-08 16:38:25 +00001362 const DataLayout *TD = TM.getDataLayout();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001363
1364 // GlobalVariables are always constant pointers themselves.
1365 const PointerType *PTy = GVar->getType();
1366 Type *ETy = PTy->getElementType();
1367
1368 if (GVar->hasExternalLinkage()) {
1369 if (GVar->hasInitializer())
1370 O << ".visible ";
1371 else
1372 O << ".extern ";
1373 }
1374
1375 if (llvm::isTexture(*GVar)) {
1376 O << ".global .texref " << llvm::getTextureName(*GVar) << ";\n";
1377 return;
1378 }
1379
1380 if (llvm::isSurface(*GVar)) {
1381 O << ".global .surfref " << llvm::getSurfaceName(*GVar) << ";\n";
1382 return;
1383 }
1384
1385 if (GVar->isDeclaration()) {
1386 // (extern) declarations, no definition or initializer
1387 // Currently the only known declaration is for an automatic __local
1388 // (.shared) promoted to global.
1389 emitPTXGlobalVariable(GVar, O);
1390 O << ";\n";
1391 return;
1392 }
1393
1394 if (llvm::isSampler(*GVar)) {
1395 O << ".global .samplerref " << llvm::getSamplerName(*GVar);
1396
Craig Topper062a2ba2014-04-25 05:30:21 +00001397 const Constant *Initializer = nullptr;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001398 if (GVar->hasInitializer())
1399 Initializer = GVar->getInitializer();
Craig Topper062a2ba2014-04-25 05:30:21 +00001400 const ConstantInt *CI = nullptr;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001401 if (Initializer)
1402 CI = dyn_cast<ConstantInt>(Initializer);
1403 if (CI) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001404 unsigned sample = CI->getZExtValue();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001405
1406 O << " = { ";
1407
Justin Holewinski0497ab12013-03-30 14:29:21 +00001408 for (int i = 0,
1409 addr = ((sample & __CLK_ADDRESS_MASK) >> __CLK_ADDRESS_BASE);
1410 i < 3; i++) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001411 O << "addr_mode_" << i << " = ";
1412 switch (addr) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001413 case 0:
1414 O << "wrap";
1415 break;
1416 case 1:
1417 O << "clamp_to_border";
1418 break;
1419 case 2:
1420 O << "clamp_to_edge";
1421 break;
1422 case 3:
1423 O << "wrap";
1424 break;
1425 case 4:
1426 O << "mirror";
1427 break;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001428 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001429 O << ", ";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001430 }
1431 O << "filter_mode = ";
Justin Holewinski0497ab12013-03-30 14:29:21 +00001432 switch ((sample & __CLK_FILTER_MASK) >> __CLK_FILTER_BASE) {
1433 case 0:
1434 O << "nearest";
1435 break;
1436 case 1:
1437 O << "linear";
1438 break;
1439 case 2:
Craig Topper2a30d782014-06-18 05:05:13 +00001440 llvm_unreachable("Anisotropic filtering is not supported");
Justin Holewinski0497ab12013-03-30 14:29:21 +00001441 default:
1442 O << "nearest";
1443 break;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001444 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001445 if (!((sample & __CLK_NORMALIZED_MASK) >> __CLK_NORMALIZED_BASE)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001446 O << ", force_unnormalized_coords = 1";
1447 }
1448 O << " }";
1449 }
1450
1451 O << ";\n";
1452 return;
1453 }
1454
1455 if (GVar->hasPrivateLinkage()) {
1456
1457 if (!strncmp(GVar->getName().data(), "unrollpragma", 12))
1458 return;
1459
1460 // FIXME - need better way (e.g. Metadata) to avoid generating this global
1461 if (!strncmp(GVar->getName().data(), "filename", 8))
1462 return;
1463 if (GVar->use_empty())
1464 return;
1465 }
1466
Craig Topper062a2ba2014-04-25 05:30:21 +00001467 const Function *demotedFunc = nullptr;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001468 if (!processDemoted && canDemoteGlobalVar(GVar, demotedFunc)) {
1469 O << "// " << GVar->getName().str() << " has been demoted\n";
1470 if (localDecls.find(demotedFunc) != localDecls.end())
1471 localDecls[demotedFunc].push_back(GVar);
1472 else {
Justin Holewinski01f89f02013-05-20 12:13:32 +00001473 std::vector<const GlobalVariable *> temp;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001474 temp.push_back(GVar);
1475 localDecls[demotedFunc] = temp;
1476 }
1477 return;
1478 }
1479
1480 O << ".";
1481 emitPTXAddressSpace(PTy->getAddressSpace(), O);
1482 if (GVar->getAlignment() == 0)
1483 O << " .align " << (int) TD->getPrefTypeAlignment(ETy);
1484 else
1485 O << " .align " << GVar->getAlignment();
1486
Rafael Espindola08013342013-12-07 19:34:20 +00001487 if (ETy->isSingleValueType()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001488 O << " .";
Justin Holewinski700b6fa2013-05-20 12:13:28 +00001489 // Special case: ABI requires that we use .u8 for predicates
1490 if (ETy->isIntegerTy(1))
1491 O << "u8";
1492 else
1493 O << getPTXFundamentalTypeStr(ETy, false);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001494 O << " ";
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001495 O << *getSymbol(GVar);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001496
1497 // Ptx allows variable initilization only for constant and global state
1498 // spaces.
1499 if (((PTy->getAddressSpace() == llvm::ADDRESS_SPACE_GLOBAL) ||
Justin Holewinski0497ab12013-03-30 14:29:21 +00001500 (PTy->getAddressSpace() == llvm::ADDRESS_SPACE_CONST)) &&
1501 GVar->hasInitializer()) {
Justin Holewinski01f89f02013-05-20 12:13:32 +00001502 const Constant *Initializer = GVar->getInitializer();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001503 if (!Initializer->isNullValue()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001504 O << " = ";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001505 printScalarConstant(Initializer, O);
1506 }
1507 }
1508 } else {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001509 unsigned int ElementSize = 0;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001510
1511 // Although PTX has direct support for struct type and array type and
1512 // LLVM IR is very similar to PTX, the LLVM CodeGen does not support for
1513 // targets that support these high level field accesses. Structs, arrays
1514 // and vectors are lowered into arrays of bytes.
1515 switch (ETy->getTypeID()) {
1516 case Type::StructTyID:
1517 case Type::ArrayTyID:
1518 case Type::VectorTyID:
1519 ElementSize = TD->getTypeStoreSize(ETy);
1520 // Ptx allows variable initilization only for constant and
1521 // global state spaces.
1522 if (((PTy->getAddressSpace() == llvm::ADDRESS_SPACE_GLOBAL) ||
Justin Holewinski0497ab12013-03-30 14:29:21 +00001523 (PTy->getAddressSpace() == llvm::ADDRESS_SPACE_CONST)) &&
1524 GVar->hasInitializer()) {
Justin Holewinski01f89f02013-05-20 12:13:32 +00001525 const Constant *Initializer = GVar->getInitializer();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001526 if (!isa<UndefValue>(Initializer) && !Initializer->isNullValue()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001527 AggBuffer aggBuffer(ElementSize, O, *this);
1528 bufferAggregateConstant(Initializer, &aggBuffer);
1529 if (aggBuffer.numSymbols) {
1530 if (nvptxSubtarget.is64Bit()) {
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001531 O << " .u64 " << *getSymbol(GVar) << "[";
Justin Holewinski0497ab12013-03-30 14:29:21 +00001532 O << ElementSize / 8;
1533 } else {
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001534 O << " .u32 " << *getSymbol(GVar) << "[";
Justin Holewinski0497ab12013-03-30 14:29:21 +00001535 O << ElementSize / 4;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001536 }
1537 O << "]";
Justin Holewinski0497ab12013-03-30 14:29:21 +00001538 } else {
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001539 O << " .b8 " << *getSymbol(GVar) << "[";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001540 O << ElementSize;
1541 O << "]";
1542 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001543 O << " = {";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001544 aggBuffer.print();
1545 O << "}";
Justin Holewinski0497ab12013-03-30 14:29:21 +00001546 } else {
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001547 O << " .b8 " << *getSymbol(GVar);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001548 if (ElementSize) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001549 O << "[";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001550 O << ElementSize;
1551 O << "]";
1552 }
1553 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001554 } else {
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001555 O << " .b8 " << *getSymbol(GVar);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001556 if (ElementSize) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001557 O << "[";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001558 O << ElementSize;
1559 O << "]";
1560 }
1561 }
1562 break;
1563 default:
Craig Topper2a30d782014-06-18 05:05:13 +00001564 llvm_unreachable("type not supported yet");
Justin Holewinskiae556d32012-05-04 20:18:50 +00001565 }
1566
1567 }
1568 O << ";\n";
1569}
1570
1571void NVPTXAsmPrinter::emitDemotedVars(const Function *f, raw_ostream &O) {
1572 if (localDecls.find(f) == localDecls.end())
1573 return;
1574
Justin Holewinski01f89f02013-05-20 12:13:32 +00001575 std::vector<const GlobalVariable *> &gvars = localDecls[f];
Justin Holewinskiae556d32012-05-04 20:18:50 +00001576
Justin Holewinski0497ab12013-03-30 14:29:21 +00001577 for (unsigned i = 0, e = gvars.size(); i != e; ++i) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001578 O << "\t// demoted variable\n\t";
1579 printModuleLevelGV(gvars[i], O, true);
1580 }
1581}
1582
1583void NVPTXAsmPrinter::emitPTXAddressSpace(unsigned int AddressSpace,
1584 raw_ostream &O) const {
1585 switch (AddressSpace) {
1586 case llvm::ADDRESS_SPACE_LOCAL:
Justin Holewinski0497ab12013-03-30 14:29:21 +00001587 O << "local";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001588 break;
1589 case llvm::ADDRESS_SPACE_GLOBAL:
Justin Holewinski0497ab12013-03-30 14:29:21 +00001590 O << "global";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001591 break;
1592 case llvm::ADDRESS_SPACE_CONST:
Justin Holewinski0497ab12013-03-30 14:29:21 +00001593 O << "const";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001594 break;
1595 case llvm::ADDRESS_SPACE_SHARED:
Justin Holewinski0497ab12013-03-30 14:29:21 +00001596 O << "shared";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001597 break;
1598 default:
Justin Holewinski36a50992013-02-09 13:34:15 +00001599 report_fatal_error("Bad address space found while emitting PTX");
1600 break;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001601 }
1602}
1603
Justin Holewinski0497ab12013-03-30 14:29:21 +00001604std::string
1605NVPTXAsmPrinter::getPTXFundamentalTypeStr(const Type *Ty, bool useB4PTR) const {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001606 switch (Ty->getTypeID()) {
1607 default:
1608 llvm_unreachable("unexpected type");
1609 break;
1610 case Type::IntegerTyID: {
1611 unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth();
1612 if (NumBits == 1)
1613 return "pred";
1614 else if (NumBits <= 64) {
1615 std::string name = "u";
1616 return name + utostr(NumBits);
1617 } else {
1618 llvm_unreachable("Integer too large");
1619 break;
1620 }
1621 break;
1622 }
1623 case Type::FloatTyID:
1624 return "f32";
1625 case Type::DoubleTyID:
1626 return "f64";
1627 case Type::PointerTyID:
1628 if (nvptxSubtarget.is64Bit())
Justin Holewinski0497ab12013-03-30 14:29:21 +00001629 if (useB4PTR)
1630 return "b64";
1631 else
1632 return "u64";
1633 else if (useB4PTR)
1634 return "b32";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001635 else
Justin Holewinski0497ab12013-03-30 14:29:21 +00001636 return "u32";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001637 }
1638 llvm_unreachable("unexpected type");
Craig Topper062a2ba2014-04-25 05:30:21 +00001639 return nullptr;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001640}
1641
Justin Holewinski0497ab12013-03-30 14:29:21 +00001642void NVPTXAsmPrinter::emitPTXGlobalVariable(const GlobalVariable *GVar,
Justin Holewinskiae556d32012-05-04 20:18:50 +00001643 raw_ostream &O) {
1644
Micah Villmowcdfe20b2012-10-08 16:38:25 +00001645 const DataLayout *TD = TM.getDataLayout();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001646
1647 // GlobalVariables are always constant pointers themselves.
1648 const PointerType *PTy = GVar->getType();
1649 Type *ETy = PTy->getElementType();
1650
1651 O << ".";
1652 emitPTXAddressSpace(PTy->getAddressSpace(), O);
1653 if (GVar->getAlignment() == 0)
1654 O << " .align " << (int) TD->getPrefTypeAlignment(ETy);
1655 else
1656 O << " .align " << GVar->getAlignment();
1657
Rafael Espindola08013342013-12-07 19:34:20 +00001658 if (ETy->isSingleValueType()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001659 O << " .";
1660 O << getPTXFundamentalTypeStr(ETy);
1661 O << " ";
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001662 O << *getSymbol(GVar);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001663 return;
1664 }
1665
Justin Holewinski0497ab12013-03-30 14:29:21 +00001666 int64_t ElementSize = 0;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001667
1668 // Although PTX has direct support for struct type and array type and LLVM IR
1669 // is very similar to PTX, the LLVM CodeGen does not support for targets that
1670 // support these high level field accesses. Structs and arrays are lowered
1671 // into arrays of bytes.
1672 switch (ETy->getTypeID()) {
1673 case Type::StructTyID:
1674 case Type::ArrayTyID:
1675 case Type::VectorTyID:
1676 ElementSize = TD->getTypeStoreSize(ETy);
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001677 O << " .b8 " << *getSymbol(GVar) << "[";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001678 if (ElementSize) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001679 O << itostr(ElementSize);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001680 }
1681 O << "]";
1682 break;
1683 default:
Craig Topper2a30d782014-06-18 05:05:13 +00001684 llvm_unreachable("type not supported yet");
Justin Holewinskiae556d32012-05-04 20:18:50 +00001685 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001686 return;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001687}
1688
Justin Holewinski0497ab12013-03-30 14:29:21 +00001689static unsigned int getOpenCLAlignment(const DataLayout *TD, Type *Ty) {
Rafael Espindola08013342013-12-07 19:34:20 +00001690 if (Ty->isSingleValueType())
Justin Holewinskiae556d32012-05-04 20:18:50 +00001691 return TD->getPrefTypeAlignment(Ty);
1692
1693 const ArrayType *ATy = dyn_cast<ArrayType>(Ty);
1694 if (ATy)
1695 return getOpenCLAlignment(TD, ATy->getElementType());
1696
1697 const VectorType *VTy = dyn_cast<VectorType>(Ty);
1698 if (VTy) {
1699 Type *ETy = VTy->getElementType();
1700 unsigned int numE = VTy->getNumElements();
1701 unsigned int alignE = TD->getPrefTypeAlignment(ETy);
1702 if (numE == 3)
Justin Holewinski0497ab12013-03-30 14:29:21 +00001703 return 4 * alignE;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001704 else
Justin Holewinski0497ab12013-03-30 14:29:21 +00001705 return numE * alignE;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001706 }
1707
1708 const StructType *STy = dyn_cast<StructType>(Ty);
1709 if (STy) {
1710 unsigned int alignStruct = 1;
1711 // Go through each element of the struct and find the
1712 // largest alignment.
Justin Holewinski0497ab12013-03-30 14:29:21 +00001713 for (unsigned i = 0, e = STy->getNumElements(); i != e; i++) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001714 Type *ETy = STy->getElementType(i);
1715 unsigned int align = getOpenCLAlignment(TD, ETy);
1716 if (align > alignStruct)
1717 alignStruct = align;
1718 }
1719 return alignStruct;
1720 }
1721
1722 const FunctionType *FTy = dyn_cast<FunctionType>(Ty);
1723 if (FTy)
Chandler Carruth5da3f052012-11-01 09:14:31 +00001724 return TD->getPointerPrefAlignment();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001725 return TD->getPrefTypeAlignment(Ty);
1726}
1727
1728void NVPTXAsmPrinter::printParamName(Function::const_arg_iterator I,
1729 int paramIndex, raw_ostream &O) {
1730 if ((nvptxSubtarget.getDrvInterface() == NVPTX::NVCL) ||
1731 (nvptxSubtarget.getDrvInterface() == NVPTX::CUDA))
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001732 O << *getSymbol(I->getParent()) << "_param_" << paramIndex;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001733 else {
1734 std::string argName = I->getName();
1735 const char *p = argName.c_str();
1736 while (*p) {
1737 if (*p == '.')
1738 O << "_";
1739 else
1740 O << *p;
1741 p++;
1742 }
1743 }
1744}
1745
1746void NVPTXAsmPrinter::printParamName(int paramIndex, raw_ostream &O) {
1747 Function::const_arg_iterator I, E;
1748 int i = 0;
1749
1750 if ((nvptxSubtarget.getDrvInterface() == NVPTX::NVCL) ||
1751 (nvptxSubtarget.getDrvInterface() == NVPTX::CUDA)) {
1752 O << *CurrentFnSym << "_param_" << paramIndex;
1753 return;
1754 }
1755
1756 for (I = F->arg_begin(), E = F->arg_end(); I != E; ++I, i++) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001757 if (i == paramIndex) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001758 printParamName(I, paramIndex, O);
1759 return;
1760 }
1761 }
1762 llvm_unreachable("paramIndex out of bound");
1763}
1764
Justin Holewinski0497ab12013-03-30 14:29:21 +00001765void NVPTXAsmPrinter::emitFunctionParamList(const Function *F, raw_ostream &O) {
Micah Villmowcdfe20b2012-10-08 16:38:25 +00001766 const DataLayout *TD = TM.getDataLayout();
Bill Wendlinge94d8432012-12-07 23:16:57 +00001767 const AttributeSet &PAL = F->getAttributes();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001768 const TargetLowering *TLI = TM.getTargetLowering();
1769 Function::const_arg_iterator I, E;
1770 unsigned paramIndex = 0;
1771 bool first = true;
1772 bool isKernelFunc = llvm::isKernelFunction(*F);
1773 bool isABI = (nvptxSubtarget.getSmVersion() >= 20);
1774 MVT thePointerTy = TLI->getPointerTy();
1775
1776 O << "(\n";
1777
1778 for (I = F->arg_begin(), E = F->arg_end(); I != E; ++I, paramIndex++) {
Justin Holewinskie9884092013-03-24 21:17:47 +00001779 Type *Ty = I->getType();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001780
1781 if (!first)
1782 O << ",\n";
1783
1784 first = false;
1785
1786 // Handle image/sampler parameters
Justin Holewinski30d56a72014-04-09 15:39:15 +00001787 if (isKernelFunction(*F)) {
1788 if (isSampler(*I) || isImage(*I)) {
1789 if (isImage(*I)) {
1790 std::string sname = I->getName();
1791 if (isImageWriteOnly(*I) || isImageReadWrite(*I)) {
1792 if (nvptxSubtarget.hasImageHandles())
1793 O << "\t.param .u64 .ptr .surfref ";
1794 else
1795 O << "\t.param .surfref ";
1796 O << *CurrentFnSym << "_param_" << paramIndex;
1797 }
1798 else { // Default image is read_only
1799 if (nvptxSubtarget.hasImageHandles())
1800 O << "\t.param .u64 .ptr .texref ";
1801 else
1802 O << "\t.param .texref ";
1803 O << *CurrentFnSym << "_param_" << paramIndex;
1804 }
1805 } else {
1806 if (nvptxSubtarget.hasImageHandles())
1807 O << "\t.param .u64 .ptr .samplerref ";
1808 else
1809 O << "\t.param .samplerref ";
1810 O << *CurrentFnSym << "_param_" << paramIndex;
1811 }
1812 continue;
1813 }
Justin Holewinskiae556d32012-05-04 20:18:50 +00001814 }
1815
Justin Holewinski0497ab12013-03-30 14:29:21 +00001816 if (PAL.hasAttribute(paramIndex + 1, Attribute::ByVal) == false) {
Gautam Chakrabarti2c283402014-01-28 18:35:29 +00001817 if (Ty->isAggregateType() || Ty->isVectorTy()) {
1818 // Just print .param .align <a> .b8 .param[size];
Justin Holewinskie9884092013-03-24 21:17:47 +00001819 // <a> = PAL.getparamalignment
1820 // size = typeallocsize of element type
Justin Holewinski0497ab12013-03-30 14:29:21 +00001821 unsigned align = PAL.getParamAlignment(paramIndex + 1);
Justin Holewinskie9884092013-03-24 21:17:47 +00001822 if (align == 0)
1823 align = TD->getABITypeAlignment(Ty);
1824
1825 unsigned sz = TD->getTypeAllocSize(Ty);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001826 O << "\t.param .align " << align << " .b8 ";
Justin Holewinskie9884092013-03-24 21:17:47 +00001827 printParamName(I, paramIndex, O);
1828 O << "[" << sz << "]";
1829
1830 continue;
1831 }
Justin Holewinskiae556d32012-05-04 20:18:50 +00001832 // Just a scalar
1833 const PointerType *PTy = dyn_cast<PointerType>(Ty);
1834 if (isKernelFunc) {
1835 if (PTy) {
1836 // Special handling for pointer arguments to kernel
1837 O << "\t.param .u" << thePointerTy.getSizeInBits() << " ";
1838
1839 if (nvptxSubtarget.getDrvInterface() != NVPTX::CUDA) {
1840 Type *ETy = PTy->getElementType();
1841 int addrSpace = PTy->getAddressSpace();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001842 switch (addrSpace) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001843 default:
1844 O << ".ptr ";
1845 break;
Justin Holewinskib96d1392013-06-10 13:29:47 +00001846 case llvm::ADDRESS_SPACE_CONST:
Justin Holewinskiae556d32012-05-04 20:18:50 +00001847 O << ".ptr .const ";
1848 break;
1849 case llvm::ADDRESS_SPACE_SHARED:
1850 O << ".ptr .shared ";
1851 break;
1852 case llvm::ADDRESS_SPACE_GLOBAL:
Justin Holewinskiae556d32012-05-04 20:18:50 +00001853 O << ".ptr .global ";
1854 break;
1855 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001856 O << ".align " << (int) getOpenCLAlignment(TD, ETy) << " ";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001857 }
1858 printParamName(I, paramIndex, O);
1859 continue;
1860 }
1861
1862 // non-pointer scalar to kernel func
Justin Holewinski700b6fa2013-05-20 12:13:28 +00001863 O << "\t.param .";
1864 // Special case: predicate operands become .u8 types
1865 if (Ty->isIntegerTy(1))
1866 O << "u8";
1867 else
1868 O << getPTXFundamentalTypeStr(Ty);
1869 O << " ";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001870 printParamName(I, paramIndex, O);
1871 continue;
1872 }
1873 // Non-kernel function, just print .param .b<size> for ABI
Alp Tokerf907b892013-12-05 05:44:44 +00001874 // and .reg .b<size> for non-ABI
Justin Holewinskiae556d32012-05-04 20:18:50 +00001875 unsigned sz = 0;
1876 if (isa<IntegerType>(Ty)) {
1877 sz = cast<IntegerType>(Ty)->getBitWidth();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001878 if (sz < 32)
1879 sz = 32;
1880 } else if (isa<PointerType>(Ty))
Justin Holewinskiae556d32012-05-04 20:18:50 +00001881 sz = thePointerTy.getSizeInBits();
1882 else
1883 sz = Ty->getPrimitiveSizeInBits();
1884 if (isABI)
1885 O << "\t.param .b" << sz << " ";
1886 else
1887 O << "\t.reg .b" << sz << " ";
1888 printParamName(I, paramIndex, O);
1889 continue;
1890 }
1891
1892 // param has byVal attribute. So should be a pointer
1893 const PointerType *PTy = dyn_cast<PointerType>(Ty);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001894 assert(PTy && "Param with byval attribute should be a pointer type");
Justin Holewinskiae556d32012-05-04 20:18:50 +00001895 Type *ETy = PTy->getElementType();
1896
1897 if (isABI || isKernelFunc) {
Gautam Chakrabarti2c283402014-01-28 18:35:29 +00001898 // Just print .param .align <a> .b8 .param[size];
Justin Holewinskiae556d32012-05-04 20:18:50 +00001899 // <a> = PAL.getparamalignment
1900 // size = typeallocsize of element type
Justin Holewinski0497ab12013-03-30 14:29:21 +00001901 unsigned align = PAL.getParamAlignment(paramIndex + 1);
Justin Holewinski2dc9d072012-11-09 23:50:24 +00001902 if (align == 0)
1903 align = TD->getABITypeAlignment(ETy);
1904
Justin Holewinskiae556d32012-05-04 20:18:50 +00001905 unsigned sz = TD->getTypeAllocSize(ETy);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001906 O << "\t.param .align " << align << " .b8 ";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001907 printParamName(I, paramIndex, O);
1908 O << "[" << sz << "]";
1909 continue;
1910 } else {
1911 // Split the ETy into constituent parts and
1912 // print .param .b<size> <name> for each part.
1913 // Further, if a part is vector, print the above for
1914 // each vector element.
1915 SmallVector<EVT, 16> vtparts;
1916 ComputeValueVTs(*TLI, ETy, vtparts);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001917 for (unsigned i = 0, e = vtparts.size(); i != e; ++i) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001918 unsigned elems = 1;
1919 EVT elemtype = vtparts[i];
1920 if (vtparts[i].isVector()) {
1921 elems = vtparts[i].getVectorNumElements();
1922 elemtype = vtparts[i].getVectorElementType();
1923 }
1924
Justin Holewinski0497ab12013-03-30 14:29:21 +00001925 for (unsigned j = 0, je = elems; j != je; ++j) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001926 unsigned sz = elemtype.getSizeInBits();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001927 if (elemtype.isInteger() && (sz < 32))
1928 sz = 32;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001929 O << "\t.reg .b" << sz << " ";
1930 printParamName(I, paramIndex, O);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001931 if (j < je - 1)
1932 O << ",\n";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001933 ++paramIndex;
1934 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001935 if (i < e - 1)
Justin Holewinskiae556d32012-05-04 20:18:50 +00001936 O << ",\n";
1937 }
1938 --paramIndex;
1939 continue;
1940 }
1941 }
1942
1943 O << "\n)\n";
1944}
1945
1946void NVPTXAsmPrinter::emitFunctionParamList(const MachineFunction &MF,
1947 raw_ostream &O) {
1948 const Function *F = MF.getFunction();
1949 emitFunctionParamList(F, O);
1950}
1951
Justin Holewinski0497ab12013-03-30 14:29:21 +00001952void NVPTXAsmPrinter::setAndEmitFunctionVirtualRegisters(
1953 const MachineFunction &MF) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001954 SmallString<128> Str;
1955 raw_svector_ostream O(Str);
1956
1957 // Map the global virtual register number to a register class specific
1958 // virtual register number starting from 1 with that class.
1959 const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo();
1960 //unsigned numRegClasses = TRI->getNumRegClasses();
1961
1962 // Emit the Fake Stack Object
1963 const MachineFrameInfo *MFI = MF.getFrameInfo();
1964 int NumBytes = (int) MFI->getStackSize();
1965 if (NumBytes) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001966 O << "\t.local .align " << MFI->getMaxAlignment() << " .b8 \t" << DEPOTNAME
1967 << getFunctionNumber() << "[" << NumBytes << "];\n";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001968 if (nvptxSubtarget.is64Bit()) {
1969 O << "\t.reg .b64 \t%SP;\n";
1970 O << "\t.reg .b64 \t%SPL;\n";
Justin Holewinski0497ab12013-03-30 14:29:21 +00001971 } else {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001972 O << "\t.reg .b32 \t%SP;\n";
1973 O << "\t.reg .b32 \t%SPL;\n";
1974 }
1975 }
1976
1977 // Go through all virtual registers to establish the mapping between the
1978 // global virtual
1979 // register number and the per class virtual register number.
1980 // We use the per class virtual register number in the ptx output.
1981 unsigned int numVRs = MRI->getNumVirtRegs();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001982 for (unsigned i = 0; i < numVRs; i++) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001983 unsigned int vr = TRI->index2VirtReg(i);
1984 const TargetRegisterClass *RC = MRI->getRegClass(vr);
Justin Holewinskidbb3b2f2013-05-31 12:14:49 +00001985 DenseMap<unsigned, unsigned> &regmap = VRegMapping[RC];
Justin Holewinskiae556d32012-05-04 20:18:50 +00001986 int n = regmap.size();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001987 regmap.insert(std::make_pair(vr, n + 1));
Justin Holewinskiae556d32012-05-04 20:18:50 +00001988 }
1989
1990 // Emit register declarations
1991 // @TODO: Extract out the real register usage
Justin Holewinskidbb3b2f2013-05-31 12:14:49 +00001992 // O << "\t.reg .pred %p<" << NVPTXNumRegisters << ">;\n";
1993 // O << "\t.reg .s16 %rc<" << NVPTXNumRegisters << ">;\n";
1994 // O << "\t.reg .s16 %rs<" << NVPTXNumRegisters << ">;\n";
1995 // O << "\t.reg .s32 %r<" << NVPTXNumRegisters << ">;\n";
1996 // O << "\t.reg .s64 %rl<" << NVPTXNumRegisters << ">;\n";
1997 // O << "\t.reg .f32 %f<" << NVPTXNumRegisters << ">;\n";
1998 // O << "\t.reg .f64 %fl<" << NVPTXNumRegisters << ">;\n";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001999
2000 // Emit declaration of the virtual registers or 'physical' registers for
2001 // each register class
Justin Holewinskidbb3b2f2013-05-31 12:14:49 +00002002 for (unsigned i=0; i< TRI->getNumRegClasses(); i++) {
2003 const TargetRegisterClass *RC = TRI->getRegClass(i);
2004 DenseMap<unsigned, unsigned> &regmap = VRegMapping[RC];
2005 std::string rcname = getNVPTXRegClassName(RC);
2006 std::string rcStr = getNVPTXRegClassStr(RC);
2007 int n = regmap.size();
Justin Holewinskiae556d32012-05-04 20:18:50 +00002008
Justin Holewinskidbb3b2f2013-05-31 12:14:49 +00002009 // Only declare those registers that may be used.
2010 if (n) {
2011 O << "\t.reg " << rcname << " \t" << rcStr << "<" << (n+1)
2012 << ">;\n";
2013 }
2014 }
Justin Holewinskiae556d32012-05-04 20:18:50 +00002015
2016 OutStreamer.EmitRawText(O.str());
2017}
2018
Justin Holewinskiae556d32012-05-04 20:18:50 +00002019void NVPTXAsmPrinter::printFPConstant(const ConstantFP *Fp, raw_ostream &O) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00002020 APFloat APF = APFloat(Fp->getValueAPF()); // make a copy
Justin Holewinskiae556d32012-05-04 20:18:50 +00002021 bool ignored;
2022 unsigned int numHex;
2023 const char *lead;
2024
Justin Holewinski0497ab12013-03-30 14:29:21 +00002025 if (Fp->getType()->getTypeID() == Type::FloatTyID) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00002026 numHex = 8;
2027 lead = "0f";
Justin Holewinski0497ab12013-03-30 14:29:21 +00002028 APF.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &ignored);
Justin Holewinskiae556d32012-05-04 20:18:50 +00002029 } else if (Fp->getType()->getTypeID() == Type::DoubleTyID) {
2030 numHex = 16;
2031 lead = "0d";
Justin Holewinski0497ab12013-03-30 14:29:21 +00002032 APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &ignored);
Justin Holewinskiae556d32012-05-04 20:18:50 +00002033 } else
2034 llvm_unreachable("unsupported fp type");
2035
2036 APInt API = APF.bitcastToAPInt();
2037 std::string hexstr(utohexstr(API.getZExtValue()));
2038 O << lead;
2039 if (hexstr.length() < numHex)
2040 O << std::string(numHex - hexstr.length(), '0');
2041 O << utohexstr(API.getZExtValue());
2042}
2043
Justin Holewinski01f89f02013-05-20 12:13:32 +00002044void NVPTXAsmPrinter::printScalarConstant(const Constant *CPV, raw_ostream &O) {
2045 if (const ConstantInt *CI = dyn_cast<ConstantInt>(CPV)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00002046 O << CI->getValue();
2047 return;
2048 }
Justin Holewinski01f89f02013-05-20 12:13:32 +00002049 if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CPV)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00002050 printFPConstant(CFP, O);
2051 return;
2052 }
2053 if (isa<ConstantPointerNull>(CPV)) {
2054 O << "0";
2055 return;
2056 }
Justin Holewinski01f89f02013-05-20 12:13:32 +00002057 if (const GlobalValue *GVar = dyn_cast<GlobalValue>(CPV)) {
Justin Holewinski9d852a82014-04-09 15:39:11 +00002058 PointerType *PTy = dyn_cast<PointerType>(GVar->getType());
2059 bool IsNonGenericPointer = false;
2060 if (PTy && PTy->getAddressSpace() != 0) {
2061 IsNonGenericPointer = true;
2062 }
2063 if (EmitGeneric && !isa<Function>(CPV) && !IsNonGenericPointer) {
2064 O << "generic(";
2065 O << *getSymbol(GVar);
2066 O << ")";
2067 } else {
2068 O << *getSymbol(GVar);
2069 }
Justin Holewinskiae556d32012-05-04 20:18:50 +00002070 return;
2071 }
Justin Holewinski01f89f02013-05-20 12:13:32 +00002072 if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
2073 const Value *v = Cexpr->stripPointerCasts();
Justin Holewinski9d852a82014-04-09 15:39:11 +00002074 PointerType *PTy = dyn_cast<PointerType>(Cexpr->getType());
2075 bool IsNonGenericPointer = false;
2076 if (PTy && PTy->getAddressSpace() != 0) {
2077 IsNonGenericPointer = true;
2078 }
Justin Holewinski01f89f02013-05-20 12:13:32 +00002079 if (const GlobalValue *GVar = dyn_cast<GlobalValue>(v)) {
Justin Holewinski9d852a82014-04-09 15:39:11 +00002080 if (EmitGeneric && !isa<Function>(v) && !IsNonGenericPointer) {
2081 O << "generic(";
2082 O << *getSymbol(GVar);
2083 O << ")";
2084 } else {
2085 O << *getSymbol(GVar);
2086 }
Justin Holewinskiae556d32012-05-04 20:18:50 +00002087 return;
2088 } else {
2089 O << *LowerConstant(CPV, *this);
2090 return;
2091 }
2092 }
2093 llvm_unreachable("Not scalar type found in printScalarConstant()");
2094}
2095
Justin Holewinski01f89f02013-05-20 12:13:32 +00002096void NVPTXAsmPrinter::bufferLEByte(const Constant *CPV, int Bytes,
Justin Holewinskiae556d32012-05-04 20:18:50 +00002097 AggBuffer *aggBuffer) {
2098
Micah Villmowcdfe20b2012-10-08 16:38:25 +00002099 const DataLayout *TD = TM.getDataLayout();
Justin Holewinskiae556d32012-05-04 20:18:50 +00002100
2101 if (isa<UndefValue>(CPV) || CPV->isNullValue()) {
2102 int s = TD->getTypeAllocSize(CPV->getType());
Justin Holewinski0497ab12013-03-30 14:29:21 +00002103 if (s < Bytes)
Justin Holewinskiae556d32012-05-04 20:18:50 +00002104 s = Bytes;
2105 aggBuffer->addZeros(s);
2106 return;
2107 }
2108
2109 unsigned char *ptr;
2110 switch (CPV->getType()->getTypeID()) {
2111
2112 case Type::IntegerTyID: {
2113 const Type *ETy = CPV->getType();
Justin Holewinski0497ab12013-03-30 14:29:21 +00002114 if (ETy == Type::getInt8Ty(CPV->getContext())) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00002115 unsigned char c =
2116 (unsigned char)(dyn_cast<ConstantInt>(CPV))->getZExtValue();
2117 ptr = &c;
2118 aggBuffer->addBytes(ptr, 1, Bytes);
Justin Holewinski0497ab12013-03-30 14:29:21 +00002119 } else if (ETy == Type::getInt16Ty(CPV->getContext())) {
2120 short int16 = (short)(dyn_cast<ConstantInt>(CPV))->getZExtValue();
2121 ptr = (unsigned char *)&int16;
Justin Holewinskiae556d32012-05-04 20:18:50 +00002122 aggBuffer->addBytes(ptr, 2, Bytes);
Justin Holewinski0497ab12013-03-30 14:29:21 +00002123 } else if (ETy == Type::getInt32Ty(CPV->getContext())) {
Justin Holewinski01f89f02013-05-20 12:13:32 +00002124 if (const ConstantInt *constInt = dyn_cast<ConstantInt>(CPV)) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00002125 int int32 = (int)(constInt->getZExtValue());
2126 ptr = (unsigned char *)&int32;
Justin Holewinskiae556d32012-05-04 20:18:50 +00002127 aggBuffer->addBytes(ptr, 4, Bytes);
2128 break;
Justin Holewinski01f89f02013-05-20 12:13:32 +00002129 } else if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
2130 if (const ConstantInt *constInt = dyn_cast<ConstantInt>(
Justin Holewinski0497ab12013-03-30 14:29:21 +00002131 ConstantFoldConstantExpression(Cexpr, TD))) {
2132 int int32 = (int)(constInt->getZExtValue());
2133 ptr = (unsigned char *)&int32;
Justin Holewinskiae556d32012-05-04 20:18:50 +00002134 aggBuffer->addBytes(ptr, 4, Bytes);
2135 break;
2136 }
2137 if (Cexpr->getOpcode() == Instruction::PtrToInt) {
2138 Value *v = Cexpr->getOperand(0)->stripPointerCasts();
2139 aggBuffer->addSymbol(v);
2140 aggBuffer->addZeros(4);
2141 break;
2142 }
2143 }
Craig Topperbdf39a42012-05-24 07:02:50 +00002144 llvm_unreachable("unsupported integer const type");
Justin Holewinski0497ab12013-03-30 14:29:21 +00002145 } else if (ETy == Type::getInt64Ty(CPV->getContext())) {
Justin Holewinski01f89f02013-05-20 12:13:32 +00002146 if (const ConstantInt *constInt = dyn_cast<ConstantInt>(CPV)) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00002147 long long int64 = (long long)(constInt->getZExtValue());
2148 ptr = (unsigned char *)&int64;
Justin Holewinskiae556d32012-05-04 20:18:50 +00002149 aggBuffer->addBytes(ptr, 8, Bytes);
2150 break;
Justin Holewinski01f89f02013-05-20 12:13:32 +00002151 } else if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
2152 if (const ConstantInt *constInt = dyn_cast<ConstantInt>(
Justin Holewinski0497ab12013-03-30 14:29:21 +00002153 ConstantFoldConstantExpression(Cexpr, TD))) {
2154 long long int64 = (long long)(constInt->getZExtValue());
2155 ptr = (unsigned char *)&int64;
Justin Holewinskiae556d32012-05-04 20:18:50 +00002156 aggBuffer->addBytes(ptr, 8, Bytes);
2157 break;
2158 }
2159 if (Cexpr->getOpcode() == Instruction::PtrToInt) {
2160 Value *v = Cexpr->getOperand(0)->stripPointerCasts();
2161 aggBuffer->addSymbol(v);
2162 aggBuffer->addZeros(8);
2163 break;
2164 }
2165 }
2166 llvm_unreachable("unsupported integer const type");
Craig Topperbdf39a42012-05-24 07:02:50 +00002167 } else
Justin Holewinskiae556d32012-05-04 20:18:50 +00002168 llvm_unreachable("unsupported integer const type");
2169 break;
2170 }
2171 case Type::FloatTyID:
2172 case Type::DoubleTyID: {
Justin Holewinski01f89f02013-05-20 12:13:32 +00002173 const ConstantFP *CFP = dyn_cast<ConstantFP>(CPV);
Justin Holewinski0497ab12013-03-30 14:29:21 +00002174 const Type *Ty = CFP->getType();
Justin Holewinskiae556d32012-05-04 20:18:50 +00002175 if (Ty == Type::getFloatTy(CPV->getContext())) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00002176 float float32 = (float) CFP->getValueAPF().convertToFloat();
2177 ptr = (unsigned char *)&float32;
Justin Holewinskiae556d32012-05-04 20:18:50 +00002178 aggBuffer->addBytes(ptr, 4, Bytes);
2179 } else if (Ty == Type::getDoubleTy(CPV->getContext())) {
2180 double float64 = CFP->getValueAPF().convertToDouble();
Justin Holewinski0497ab12013-03-30 14:29:21 +00002181 ptr = (unsigned char *)&float64;
Justin Holewinskiae556d32012-05-04 20:18:50 +00002182 aggBuffer->addBytes(ptr, 8, Bytes);
Justin Holewinski0497ab12013-03-30 14:29:21 +00002183 } else {
Justin Holewinskiae556d32012-05-04 20:18:50 +00002184 llvm_unreachable("unsupported fp const type");
2185 }
2186 break;
2187 }
2188 case Type::PointerTyID: {
Justin Holewinski01f89f02013-05-20 12:13:32 +00002189 if (const GlobalValue *GVar = dyn_cast<GlobalValue>(CPV)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00002190 aggBuffer->addSymbol(GVar);
Justin Holewinski01f89f02013-05-20 12:13:32 +00002191 } else if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
2192 const Value *v = Cexpr->stripPointerCasts();
Justin Holewinskiae556d32012-05-04 20:18:50 +00002193 aggBuffer->addSymbol(v);
2194 }
2195 unsigned int s = TD->getTypeAllocSize(CPV->getType());
2196 aggBuffer->addZeros(s);
2197 break;
2198 }
2199
2200 case Type::ArrayTyID:
2201 case Type::VectorTyID:
2202 case Type::StructTyID: {
2203 if (isa<ConstantArray>(CPV) || isa<ConstantVector>(CPV) ||
Justin Holewinski95564bd2013-09-19 12:51:46 +00002204 isa<ConstantStruct>(CPV) || isa<ConstantDataSequential>(CPV)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00002205 int ElementSize = TD->getTypeAllocSize(CPV->getType());
2206 bufferAggregateConstant(CPV, aggBuffer);
Justin Holewinski0497ab12013-03-30 14:29:21 +00002207 if (Bytes > ElementSize)
2208 aggBuffer->addZeros(Bytes - ElementSize);
2209 } else if (isa<ConstantAggregateZero>(CPV))
Justin Holewinskiae556d32012-05-04 20:18:50 +00002210 aggBuffer->addZeros(Bytes);
2211 else
2212 llvm_unreachable("Unexpected Constant type");
2213 break;
2214 }
2215
2216 default:
2217 llvm_unreachable("unsupported type");
2218 }
2219}
2220
Justin Holewinski01f89f02013-05-20 12:13:32 +00002221void NVPTXAsmPrinter::bufferAggregateConstant(const Constant *CPV,
Justin Holewinskiae556d32012-05-04 20:18:50 +00002222 AggBuffer *aggBuffer) {
Micah Villmowcdfe20b2012-10-08 16:38:25 +00002223 const DataLayout *TD = TM.getDataLayout();
Justin Holewinskiae556d32012-05-04 20:18:50 +00002224 int Bytes;
2225
2226 // Old constants
2227 if (isa<ConstantArray>(CPV) || isa<ConstantVector>(CPV)) {
2228 if (CPV->getNumOperands())
2229 for (unsigned i = 0, e = CPV->getNumOperands(); i != e; ++i)
2230 bufferLEByte(cast<Constant>(CPV->getOperand(i)), 0, aggBuffer);
2231 return;
2232 }
2233
2234 if (const ConstantDataSequential *CDS =
Justin Holewinski0497ab12013-03-30 14:29:21 +00002235 dyn_cast<ConstantDataSequential>(CPV)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00002236 if (CDS->getNumElements())
2237 for (unsigned i = 0; i < CDS->getNumElements(); ++i)
2238 bufferLEByte(cast<Constant>(CDS->getElementAsConstant(i)), 0,
2239 aggBuffer);
2240 return;
2241 }
2242
Justin Holewinskiae556d32012-05-04 20:18:50 +00002243 if (isa<ConstantStruct>(CPV)) {
2244 if (CPV->getNumOperands()) {
2245 StructType *ST = cast<StructType>(CPV->getType());
2246 for (unsigned i = 0, e = CPV->getNumOperands(); i != e; ++i) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00002247 if (i == (e - 1))
Justin Holewinskiae556d32012-05-04 20:18:50 +00002248 Bytes = TD->getStructLayout(ST)->getElementOffset(0) +
Justin Holewinski0497ab12013-03-30 14:29:21 +00002249 TD->getTypeAllocSize(ST) -
2250 TD->getStructLayout(ST)->getElementOffset(i);
Justin Holewinskiae556d32012-05-04 20:18:50 +00002251 else
Justin Holewinski0497ab12013-03-30 14:29:21 +00002252 Bytes = TD->getStructLayout(ST)->getElementOffset(i + 1) -
2253 TD->getStructLayout(ST)->getElementOffset(i);
2254 bufferLEByte(cast<Constant>(CPV->getOperand(i)), Bytes, aggBuffer);
Justin Holewinskiae556d32012-05-04 20:18:50 +00002255 }
2256 }
2257 return;
2258 }
Craig Topperbdf39a42012-05-24 07:02:50 +00002259 llvm_unreachable("unsupported constant type in printAggregateConstant()");
Justin Holewinskiae556d32012-05-04 20:18:50 +00002260}
2261
2262// buildTypeNameMap - Run through symbol table looking for type names.
2263//
2264
Justin Holewinskiae556d32012-05-04 20:18:50 +00002265bool NVPTXAsmPrinter::isImageType(const Type *Ty) {
2266
2267 std::map<const Type *, std::string>::iterator PI = TypeNameMap.find(Ty);
2268
Justin Holewinski0497ab12013-03-30 14:29:21 +00002269 if (PI != TypeNameMap.end() && (!PI->second.compare("struct._image1d_t") ||
2270 !PI->second.compare("struct._image2d_t") ||
2271 !PI->second.compare("struct._image3d_t")))
Justin Holewinskiae556d32012-05-04 20:18:50 +00002272 return true;
2273
2274 return false;
2275}
2276
Justin Holewinskiae556d32012-05-04 20:18:50 +00002277
Justin Holewinski0497ab12013-03-30 14:29:21 +00002278bool NVPTXAsmPrinter::ignoreLoc(const MachineInstr &MI) {
2279 switch (MI.getOpcode()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00002280 default:
2281 return false;
Justin Holewinski0497ab12013-03-30 14:29:21 +00002282 case NVPTX::CallArgBeginInst:
2283 case NVPTX::CallArgEndInst0:
2284 case NVPTX::CallArgEndInst1:
2285 case NVPTX::CallArgF32:
2286 case NVPTX::CallArgF64:
2287 case NVPTX::CallArgI16:
2288 case NVPTX::CallArgI32:
2289 case NVPTX::CallArgI32imm:
2290 case NVPTX::CallArgI64:
Justin Holewinski0497ab12013-03-30 14:29:21 +00002291 case NVPTX::CallArgParam:
2292 case NVPTX::CallVoidInst:
2293 case NVPTX::CallVoidInstReg:
2294 case NVPTX::Callseq_End:
Justin Holewinskiae556d32012-05-04 20:18:50 +00002295 case NVPTX::CallVoidInstReg64:
Justin Holewinski0497ab12013-03-30 14:29:21 +00002296 case NVPTX::DeclareParamInst:
2297 case NVPTX::DeclareRetMemInst:
2298 case NVPTX::DeclareRetRegInst:
2299 case NVPTX::DeclareRetScalarInst:
2300 case NVPTX::DeclareScalarParamInst:
2301 case NVPTX::DeclareScalarRegInst:
2302 case NVPTX::StoreParamF32:
2303 case NVPTX::StoreParamF64:
2304 case NVPTX::StoreParamI16:
2305 case NVPTX::StoreParamI32:
2306 case NVPTX::StoreParamI64:
2307 case NVPTX::StoreParamI8:
Justin Holewinski0497ab12013-03-30 14:29:21 +00002308 case NVPTX::StoreRetvalF32:
2309 case NVPTX::StoreRetvalF64:
2310 case NVPTX::StoreRetvalI16:
2311 case NVPTX::StoreRetvalI32:
2312 case NVPTX::StoreRetvalI64:
2313 case NVPTX::StoreRetvalI8:
2314 case NVPTX::LastCallArgF32:
2315 case NVPTX::LastCallArgF64:
2316 case NVPTX::LastCallArgI16:
2317 case NVPTX::LastCallArgI32:
2318 case NVPTX::LastCallArgI32imm:
2319 case NVPTX::LastCallArgI64:
Justin Holewinski0497ab12013-03-30 14:29:21 +00002320 case NVPTX::LastCallArgParam:
2321 case NVPTX::LoadParamMemF32:
2322 case NVPTX::LoadParamMemF64:
2323 case NVPTX::LoadParamMemI16:
2324 case NVPTX::LoadParamMemI32:
2325 case NVPTX::LoadParamMemI64:
2326 case NVPTX::LoadParamMemI8:
Justin Holewinski0497ab12013-03-30 14:29:21 +00002327 case NVPTX::PrototypeInst:
2328 case NVPTX::DBG_VALUE:
Justin Holewinskiae556d32012-05-04 20:18:50 +00002329 return true;
2330 }
2331 return false;
2332}
2333
Justin Holewinskiaaa8b6e2013-08-24 01:17:23 +00002334/// PrintAsmOperand - Print out an operand for an inline asm expression.
2335///
2336bool NVPTXAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
2337 unsigned AsmVariant,
2338 const char *ExtraCode, raw_ostream &O) {
2339 if (ExtraCode && ExtraCode[0]) {
2340 if (ExtraCode[1] != 0)
2341 return true; // Unknown modifier.
2342
2343 switch (ExtraCode[0]) {
2344 default:
2345 // See if this is a generic print operand
2346 return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
2347 case 'r':
2348 break;
2349 }
2350 }
2351
2352 printOperand(MI, OpNo, O);
2353
2354 return false;
2355}
2356
2357bool NVPTXAsmPrinter::PrintAsmMemoryOperand(
2358 const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant,
2359 const char *ExtraCode, raw_ostream &O) {
2360 if (ExtraCode && ExtraCode[0])
2361 return true; // Unknown modifier
2362
2363 O << '[';
2364 printMemOperand(MI, OpNo, O);
2365 O << ']';
2366
2367 return false;
2368}
2369
2370void NVPTXAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
2371 raw_ostream &O, const char *Modifier) {
2372 const MachineOperand &MO = MI->getOperand(opNum);
2373 switch (MO.getType()) {
2374 case MachineOperand::MO_Register:
2375 if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) {
2376 if (MO.getReg() == NVPTX::VRDepot)
2377 O << DEPOTNAME << getFunctionNumber();
2378 else
2379 O << NVPTXInstPrinter::getRegisterName(MO.getReg());
2380 } else {
Justin Holewinski660597d2013-10-11 12:39:36 +00002381 emitVirtualRegister(MO.getReg(), O);
Justin Holewinskiaaa8b6e2013-08-24 01:17:23 +00002382 }
2383 return;
2384
2385 case MachineOperand::MO_Immediate:
2386 if (!Modifier)
2387 O << MO.getImm();
2388 else if (strstr(Modifier, "vec") == Modifier)
2389 printVecModifiedImmediate(MO, Modifier, O);
2390 else
2391 llvm_unreachable(
2392 "Don't know how to handle modifier on immediate operand");
2393 return;
2394
2395 case MachineOperand::MO_FPImmediate:
2396 printFPConstant(MO.getFPImm(), O);
2397 break;
2398
2399 case MachineOperand::MO_GlobalAddress:
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00002400 O << *getSymbol(MO.getGlobal());
Justin Holewinskiaaa8b6e2013-08-24 01:17:23 +00002401 break;
2402
Justin Holewinskiaaa8b6e2013-08-24 01:17:23 +00002403 case MachineOperand::MO_MachineBasicBlock:
2404 O << *MO.getMBB()->getSymbol();
2405 return;
2406
2407 default:
2408 llvm_unreachable("Operand type not supported.");
2409 }
2410}
2411
2412void NVPTXAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
2413 raw_ostream &O, const char *Modifier) {
2414 printOperand(MI, opNum, O);
2415
2416 if (Modifier && !strcmp(Modifier, "add")) {
2417 O << ", ";
2418 printOperand(MI, opNum + 1, O);
2419 } else {
2420 if (MI->getOperand(opNum + 1).isImm() &&
2421 MI->getOperand(opNum + 1).getImm() == 0)
2422 return; // don't print ',0' or '+0'
2423 O << "+";
2424 printOperand(MI, opNum + 1, O);
2425 }
2426}
2427
2428
Justin Holewinskiae556d32012-05-04 20:18:50 +00002429// Force static initialization.
2430extern "C" void LLVMInitializeNVPTXBackendAsmPrinter() {
2431 RegisterAsmPrinter<NVPTXAsmPrinter> X(TheNVPTXTarget32);
2432 RegisterAsmPrinter<NVPTXAsmPrinter> Y(TheNVPTXTarget64);
2433}
2434
Justin Holewinskiae556d32012-05-04 20:18:50 +00002435void NVPTXAsmPrinter::emitSrcInText(StringRef filename, unsigned line) {
2436 std::stringstream temp;
Justin Holewinski0497ab12013-03-30 14:29:21 +00002437 LineReader *reader = this->getReader(filename.str());
Justin Holewinskiae556d32012-05-04 20:18:50 +00002438 temp << "\n//";
2439 temp << filename.str();
2440 temp << ":";
2441 temp << line;
2442 temp << " ";
2443 temp << reader->readLine(line);
2444 temp << "\n";
2445 this->OutStreamer.EmitRawText(Twine(temp.str()));
2446}
2447
Justin Holewinskiae556d32012-05-04 20:18:50 +00002448LineReader *NVPTXAsmPrinter::getReader(std::string filename) {
Craig Topper062a2ba2014-04-25 05:30:21 +00002449 if (!reader) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00002450 reader = new LineReader(filename);
Justin Holewinskiae556d32012-05-04 20:18:50 +00002451 }
2452
2453 if (reader->fileName() != filename) {
2454 delete reader;
Justin Holewinski0497ab12013-03-30 14:29:21 +00002455 reader = new LineReader(filename);
Justin Holewinskiae556d32012-05-04 20:18:50 +00002456 }
2457
2458 return reader;
2459}
2460
Justin Holewinski0497ab12013-03-30 14:29:21 +00002461std::string LineReader::readLine(unsigned lineNum) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00002462 if (lineNum < theCurLine) {
2463 theCurLine = 0;
Justin Holewinski0497ab12013-03-30 14:29:21 +00002464 fstr.seekg(0, std::ios::beg);
Justin Holewinskiae556d32012-05-04 20:18:50 +00002465 }
2466 while (theCurLine < lineNum) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00002467 fstr.getline(buff, 500);
Justin Holewinskiae556d32012-05-04 20:18:50 +00002468 theCurLine++;
2469 }
2470 return buff;
2471}
2472
2473// Force static initialization.
2474extern "C" void LLVMInitializeNVPTXAsmPrinter() {
2475 RegisterAsmPrinter<NVPTXAsmPrinter> X(TheNVPTXTarget32);
2476 RegisterAsmPrinter<NVPTXAsmPrinter> Y(TheNVPTXTarget64);
2477}