1 //===-- PTXAsmPrinter.cpp - PTX LLVM assembly writer ----------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to PTX assembly language.
13 //===----------------------------------------------------------------------===//
15 #define DEBUG_TYPE "ptx-asm-printer"
18 #include "PTXMachineFunctionInfo.h"
19 #include "PTXTargetMachine.h"
20 #include "llvm/DerivedTypes.h"
21 #include "llvm/Module.h"
22 #include "llvm/ADT/SmallString.h"
23 #include "llvm/ADT/StringExtras.h"
24 #include "llvm/ADT/Twine.h"
25 #include "llvm/Analysis/DebugInfo.h"
26 #include "llvm/CodeGen/AsmPrinter.h"
27 #include "llvm/CodeGen/MachineFrameInfo.h"
28 #include "llvm/CodeGen/MachineInstr.h"
29 #include "llvm/CodeGen/MachineRegisterInfo.h"
30 #include "llvm/MC/MCContext.h"
31 #include "llvm/MC/MCStreamer.h"
32 #include "llvm/MC/MCSymbol.h"
33 #include "llvm/Target/Mangler.h"
34 #include "llvm/Target/TargetLoweringObjectFile.h"
35 #include "llvm/Target/TargetRegistry.h"
36 #include "llvm/Support/CommandLine.h"
37 #include "llvm/Support/Debug.h"
38 #include "llvm/Support/ErrorHandling.h"
39 #include "llvm/Support/MathExtras.h"
40 #include "llvm/Support/Path.h"
41 #include "llvm/Support/raw_ostream.h"
46 class PTXAsmPrinter
: public AsmPrinter
{
48 explicit PTXAsmPrinter(TargetMachine
&TM
, MCStreamer
&Streamer
)
49 : AsmPrinter(TM
, Streamer
) {}
51 const char *getPassName() const { return "PTX Assembly Printer"; }
53 bool doFinalization(Module
&M
);
55 virtual void EmitStartOfAsmFile(Module
&M
);
57 virtual bool runOnMachineFunction(MachineFunction
&MF
);
59 virtual void EmitFunctionBodyStart();
60 virtual void EmitFunctionBodyEnd() { OutStreamer
.EmitRawText(Twine("}")); }
62 virtual void EmitInstruction(const MachineInstr
*MI
);
64 void printOperand(const MachineInstr
*MI
, int opNum
, raw_ostream
&OS
);
65 void printMemOperand(const MachineInstr
*MI
, int opNum
, raw_ostream
&OS
,
66 const char *Modifier
= 0);
67 void printParamOperand(const MachineInstr
*MI
, int opNum
, raw_ostream
&OS
,
68 const char *Modifier
= 0);
69 void printReturnOperand(const MachineInstr
*MI
, int opNum
, raw_ostream
&OS
,
70 const char *Modifier
= 0);
71 void printPredicateOperand(const MachineInstr
*MI
, raw_ostream
&O
);
73 unsigned GetOrCreateSourceID(StringRef FileName
,
77 void printInstruction(const MachineInstr
*MI
, raw_ostream
&OS
);
78 static const char *getRegisterName(unsigned RegNo
);
81 void EmitVariableDeclaration(const GlobalVariable
*gv
);
82 void EmitFunctionDeclaration();
84 StringMap
<unsigned> SourceIdMap
;
85 }; // class PTXAsmPrinter
88 static const char PARAM_PREFIX
[] = "__param_";
89 static const char RETURN_PREFIX
[] = "__ret_";
91 static const char *getRegisterTypeName(unsigned RegNo
) {
92 #define TEST_REGCLS(cls, clsstr) \
93 if (PTX::cls ## RegisterClass->contains(RegNo)) return # clsstr;
94 TEST_REGCLS(RegPred
, pred
);
95 TEST_REGCLS(RegI16
, b16
);
96 TEST_REGCLS(RegI32
, b32
);
97 TEST_REGCLS(RegI64
, b64
);
98 TEST_REGCLS(RegF32
, b32
);
99 TEST_REGCLS(RegF64
, b64
);
102 llvm_unreachable("Not in any register class!");
106 static const char *getStateSpaceName(unsigned addressSpace
) {
107 switch (addressSpace
) {
108 default: llvm_unreachable("Unknown state space");
109 case PTX::GLOBAL
: return "global";
110 case PTX::CONSTANT
: return "const";
111 case PTX::LOCAL
: return "local";
112 case PTX::PARAMETER
: return "param";
113 case PTX::SHARED
: return "shared";
118 static const char *getTypeName(const Type
* type
) {
120 switch (type
->getTypeID()) {
121 default: llvm_unreachable("Unknown type");
122 case Type::FloatTyID
: return ".f32";
123 case Type::DoubleTyID
: return ".f64";
124 case Type::IntegerTyID
:
125 switch (type
->getPrimitiveSizeInBits()) {
126 default: llvm_unreachable("Unknown integer bit-width");
127 case 16: return ".u16";
128 case 32: return ".u32";
129 case 64: return ".u64";
131 case Type::ArrayTyID
:
132 case Type::PointerTyID
:
133 type
= dyn_cast
<const SequentialType
>(type
)->getElementType();
140 bool PTXAsmPrinter::doFinalization(Module
&M
) {
141 // XXX Temproarily remove global variables so that doFinalization() will not
142 // emit them again (global variables are emitted at beginning).
144 Module::GlobalListType
&global_list
= M
.getGlobalList();
145 int i
, n
= global_list
.size();
146 GlobalVariable
**gv_array
= new GlobalVariable
* [n
];
148 // first, back-up GlobalVariable in gv_array
150 for (Module::global_iterator I
= global_list
.begin(), E
= global_list
.end();
154 // second, empty global_list
155 while (!global_list
.empty())
156 global_list
.remove(global_list
.begin());
158 // call doFinalization
159 bool ret
= AsmPrinter::doFinalization(M
);
161 // now we restore global variables
162 for (i
= 0; i
< n
; i
++)
163 global_list
.insert(global_list
.end(), gv_array
[i
]);
169 void PTXAsmPrinter::EmitStartOfAsmFile(Module
&M
)
171 const PTXSubtarget
& ST
= TM
.getSubtarget
<PTXSubtarget
>();
173 OutStreamer
.EmitRawText(Twine("\t.version " + ST
.getPTXVersionString()));
174 OutStreamer
.EmitRawText(Twine("\t.target " + ST
.getTargetString() +
175 (ST
.supportsDouble() ? ""
176 : ", map_f64_to_f32")));
177 // .address_size directive is optional, but it must immediately follow
178 // the .target directive if present within a module
179 if (ST
.supportsPTX23()) {
180 std::string addrSize
= ST
.is64Bit() ? "64" : "32";
181 OutStreamer
.EmitRawText(Twine("\t.address_size " + addrSize
));
184 OutStreamer
.AddBlankLine();
186 // Define any .file directives
187 DebugInfoFinder DbgFinder
;
188 DbgFinder
.processModule(M
);
190 for (DebugInfoFinder::iterator I
= DbgFinder
.compile_unit_begin(),
191 E
= DbgFinder
.compile_unit_end(); I
!= E
; ++I
) {
192 DICompileUnit
DIUnit(*I
);
193 StringRef FN
= DIUnit
.getFilename();
194 StringRef Dir
= DIUnit
.getDirectory();
195 GetOrCreateSourceID(FN
, Dir
);
198 OutStreamer
.AddBlankLine();
200 // declare global variables
201 for (Module::const_global_iterator i
= M
.global_begin(), e
= M
.global_end();
203 EmitVariableDeclaration(i
);
206 bool PTXAsmPrinter::runOnMachineFunction(MachineFunction
&MF
) {
207 SetupMachineFunction(MF
);
208 EmitFunctionDeclaration();
213 void PTXAsmPrinter::EmitFunctionBodyStart() {
214 OutStreamer
.EmitRawText(Twine("{"));
216 const PTXMachineFunctionInfo
*MFI
= MF
->getInfo
<PTXMachineFunctionInfo
>();
218 // Print local variable definition
219 for (PTXMachineFunctionInfo::reg_iterator
220 i
= MFI
->localVarRegBegin(), e
= MFI
->localVarRegEnd(); i
!= e
; ++ i
) {
223 std::string def
= "\t.reg .";
224 def
+= getRegisterTypeName(reg
);
226 def
+= getRegisterName(reg
);
228 OutStreamer
.EmitRawText(Twine(def
));
231 const MachineFrameInfo
* FrameInfo
= MF
->getFrameInfo();
232 DEBUG(dbgs() << "Have " << FrameInfo
->getNumObjects()
233 << " frame object(s)\n");
234 for (unsigned i
= 0, e
= FrameInfo
->getNumObjects(); i
!= e
; ++i
) {
235 DEBUG(dbgs() << "Size of object: " << FrameInfo
->getObjectSize(i
) << "\n");
236 if (FrameInfo
->getObjectSize(i
) > 0) {
237 std::string def
= "\t.reg .b";
238 def
+= utostr(FrameInfo
->getObjectSize(i
)*8); // Convert to bits
242 OutStreamer
.EmitRawText(Twine(def
));
247 void PTXAsmPrinter::EmitInstruction(const MachineInstr
*MI
) {
251 raw_string_ostream
OS(str
);
253 DebugLoc DL
= MI
->getDebugLoc();
254 if (!DL
.isUnknown()) {
256 const MDNode
*S
= DL
.getScope(MF
->getFunction()->getContext());
258 // This is taken from DwarfDebug.cpp, which is conveniently not a public
264 DIDescriptor
Scope(S
);
265 if (Scope
.isCompileUnit()) {
267 Fn
= CU
.getFilename();
268 Dir
= CU
.getDirectory();
269 } else if (Scope
.isFile()) {
271 Fn
= F
.getFilename();
272 Dir
= F
.getDirectory();
273 } else if (Scope
.isSubprogram()) {
275 Fn
= SP
.getFilename();
276 Dir
= SP
.getDirectory();
277 } else if (Scope
.isLexicalBlock()) {
278 DILexicalBlock
DB(S
);
279 Fn
= DB
.getFilename();
280 Dir
= DB
.getDirectory();
282 assert(0 && "Unexpected scope info");
284 Src
= GetOrCreateSourceID(Fn
, Dir
);
286 OutStreamer
.EmitDwarfLocDirective(Src
, DL
.getLine(), DL
.getCol(),
289 const MCDwarfLoc
& MDL
= OutContext
.getCurrentDwarfLoc();
292 OS
<< utostr(MDL
.getFileNum());
294 OS
<< utostr(MDL
.getLine());
296 OS
<< utostr(MDL
.getColumn());
302 printPredicateOperand(MI
, OS
);
304 // Write instruction to str
305 printInstruction(MI
, OS
);
309 StringRef strref
= StringRef(str
);
310 OutStreamer
.EmitRawText(strref
);
313 void PTXAsmPrinter::printOperand(const MachineInstr
*MI
, int opNum
,
315 const MachineOperand
&MO
= MI
->getOperand(opNum
);
317 switch (MO
.getType()) {
319 llvm_unreachable("<unknown operand type>");
321 case MachineOperand::MO_GlobalAddress
:
322 OS
<< *Mang
->getSymbol(MO
.getGlobal());
324 case MachineOperand::MO_Immediate
:
325 OS
<< (long) MO
.getImm();
327 case MachineOperand::MO_MachineBasicBlock
:
328 OS
<< *MO
.getMBB()->getSymbol();
330 case MachineOperand::MO_Register
:
331 OS
<< getRegisterName(MO
.getReg());
333 case MachineOperand::MO_FPImmediate
:
334 APInt constFP
= MO
.getFPImm()->getValueAPF().bitcastToAPInt();
335 bool isFloat
= MO
.getFPImm()->getType()->getTypeID() == Type::FloatTyID
;
336 // Emit 0F for 32-bit floats and 0D for 64-bit doubles.
343 // Emit the encoded floating-point value.
344 if (constFP
.getZExtValue() > 0) {
345 OS
<< constFP
.toString(16, false);
349 // If We have a double-precision zero, pad to 8-bytes.
358 void PTXAsmPrinter::printMemOperand(const MachineInstr
*MI
, int opNum
,
359 raw_ostream
&OS
, const char *Modifier
) {
360 printOperand(MI
, opNum
, OS
);
362 if (MI
->getOperand(opNum
+1).isImm() && MI
->getOperand(opNum
+1).getImm() == 0)
363 return; // don't print "+0"
366 printOperand(MI
, opNum
+1, OS
);
369 void PTXAsmPrinter::printParamOperand(const MachineInstr
*MI
, int opNum
,
370 raw_ostream
&OS
, const char *Modifier
) {
371 OS
<< PARAM_PREFIX
<< (int) MI
->getOperand(opNum
).getImm() + 1;
374 void PTXAsmPrinter::printReturnOperand(const MachineInstr
*MI
, int opNum
,
375 raw_ostream
&OS
, const char *Modifier
) {
376 OS
<< RETURN_PREFIX
<< (int) MI
->getOperand(opNum
).getImm() + 1;
379 void PTXAsmPrinter::EmitVariableDeclaration(const GlobalVariable
*gv
) {
380 // Check to see if this is a special global used by LLVM, if so, emit it.
381 if (EmitSpecialLLVMGlobal(gv
))
384 MCSymbol
*gvsym
= Mang
->getSymbol(gv
);
386 assert(gvsym
->isUndefined() && "Cannot define a symbol twice!");
390 // check if it is defined in some other translation unit
391 if (gv
->isDeclaration())
394 // state space: e.g., .global
396 decl
+= getStateSpaceName(gv
->getType()->getAddressSpace());
399 // alignment (optional)
400 unsigned alignment
= gv
->getAlignment();
401 if (alignment
!= 0) {
403 decl
+= utostr(Log2_32(gv
->getAlignment()));
408 if (PointerType::classof(gv
->getType())) {
409 const PointerType
* pointerTy
= dyn_cast
<const PointerType
>(gv
->getType());
410 const Type
* elementTy
= pointerTy
->getElementType();
413 decl
+= gvsym
->getName();
416 if (elementTy
->isArrayTy())
418 assert(elementTy
->isArrayTy() && "Only pointers to arrays are supported");
420 const ArrayType
* arrayTy
= dyn_cast
<const ArrayType
>(elementTy
);
421 elementTy
= arrayTy
->getElementType();
423 unsigned numElements
= arrayTy
->getNumElements();
425 while (elementTy
->isArrayTy()) {
427 arrayTy
= dyn_cast
<const ArrayType
>(elementTy
);
428 elementTy
= arrayTy
->getElementType();
430 numElements
*= arrayTy
->getNumElements();
433 // FIXME: isPrimitiveType() == false for i16?
434 assert(elementTy
->isSingleValueType() &&
435 "Non-primitive types are not handled");
437 // Compute the size of the array, in bytes.
438 uint64_t arraySize
= (elementTy
->getPrimitiveSizeInBits() >> 3)
441 decl
+= utostr(arraySize
);
446 // handle string constants (assume ConstantArray means string)
448 if (gv
->hasInitializer())
450 const Constant
*C
= gv
->getInitializer();
451 if (const ConstantArray
*CA
= dyn_cast
<ConstantArray
>(C
))
455 for (unsigned i
= 0, e
= C
->getNumOperands(); i
!= e
; ++i
)
457 if (i
> 0) decl
+= ",";
460 utohexstr(cast
<ConstantInt
>(CA
->getOperand(i
))->getZExtValue());
468 // Note: this is currently the fall-through case and most likely generates
470 decl
+= getTypeName(gv
->getType());
473 decl
+= gvsym
->getName();
475 if (ArrayType::classof(gv
->getType()) ||
476 PointerType::classof(gv
->getType()))
482 OutStreamer
.EmitRawText(Twine(decl
));
484 OutStreamer
.AddBlankLine();
487 void PTXAsmPrinter::EmitFunctionDeclaration() {
488 // The function label could have already been emitted if two symbols end up
489 // conflicting due to asm renaming. Detect this and emit an error.
490 if (!CurrentFnSym
->isUndefined()) {
491 report_fatal_error("'" + Twine(CurrentFnSym
->getName()) +
492 "' label emitted multiple times to assembly file");
496 const PTXMachineFunctionInfo
*MFI
= MF
->getInfo
<PTXMachineFunctionInfo
>();
497 const bool isKernel
= MFI
->isKernel();
498 const PTXSubtarget
& ST
= TM
.getSubtarget
<PTXSubtarget
>();
500 std::string decl
= isKernel
? ".entry" : ".func";
506 for (PTXMachineFunctionInfo::ret_iterator
507 i
= MFI
->retRegBegin(), e
= MFI
->retRegEnd(), b
= i
;
513 decl
+= getRegisterTypeName(*i
);
515 decl
+= getRegisterName(*i
);
520 // Print function name
522 decl
+= CurrentFnSym
->getName().str();
529 for (PTXMachineFunctionInfo::reg_iterator
530 i
= MFI
->argRegBegin(), e
= MFI
->argRegEnd(), b
= i
;
535 if (isKernel
|| ST
.useParamSpaceForDeviceArgs()) {
539 decl
+= PARAM_PREFIX
;
540 decl
+= utostr(++cnt
);
543 decl
+= getRegisterTypeName(*i
);
545 decl
+= getRegisterName(*i
);
550 OutStreamer
.EmitRawText(Twine(decl
));
554 printPredicateOperand(const MachineInstr
*MI
, raw_ostream
&O
) {
555 int i
= MI
->findFirstPredOperandIdx();
557 llvm_unreachable("missing predicate operand");
559 unsigned reg
= MI
->getOperand(i
).getReg();
560 int predOp
= MI
->getOperand(i
+1).getImm();
562 DEBUG(dbgs() << "predicate: (" << reg
<< ", " << predOp
<< ")\n");
564 if (reg
!= PTX::NoRegister
) {
566 if (predOp
== PTX::PRED_NEGATE
)
568 O
<< getRegisterName(reg
);
572 unsigned PTXAsmPrinter::GetOrCreateSourceID(StringRef FileName
,
574 // If FE did not provide a file name, then assume stdin.
575 if (FileName
.empty())
576 return GetOrCreateSourceID("<stdin>", StringRef());
578 // MCStream expects full path name as filename.
579 if (!DirName
.empty() && !sys::path::is_absolute(FileName
)) {
580 SmallString
<128> FullPathName
= DirName
;
581 sys::path::append(FullPathName
, FileName
);
582 // Here FullPathName will be copied into StringMap by GetOrCreateSourceID.
583 return GetOrCreateSourceID(StringRef(FullPathName
), StringRef());
586 StringMapEntry
<unsigned> &Entry
= SourceIdMap
.GetOrCreateValue(FileName
);
587 if (Entry
.getValue())
588 return Entry
.getValue();
590 unsigned SrcId
= SourceIdMap
.size();
591 Entry
.setValue(SrcId
);
593 // Print out a .file directive to specify files for .loc directives.
594 OutStreamer
.EmitDwarfFileDirective(SrcId
, Entry
.getKey());
599 #include "PTXGenAsmWriter.inc"
601 // Force static initialization.
602 extern "C" void LLVMInitializePTXAsmPrinter() {
603 RegisterAsmPrinter
<PTXAsmPrinter
> X(ThePTX32Target
);
604 RegisterAsmPrinter
<PTXAsmPrinter
> Y(ThePTX64Target
);