blob: b861807b6331b4f7e90ad73af6a774b16e219d9a [file] [log] [blame]
Nick Lewyckyf7a3c502010-09-07 18:14:24 +00001//===-- PTXAsmPrinter.cpp - PTX 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 PTX assembly language.
12//
13//===----------------------------------------------------------------------===//
14
Che-Liang Chioudf659632010-11-08 03:06:08 +000015#define DEBUG_TYPE "ptx-asm-printer"
16
Nick Lewyckyf7a3c502010-09-07 18:14:24 +000017#include "PTX.h"
Che-Liang Chioudf659632010-11-08 03:06:08 +000018#include "PTXMachineFunctionInfo.h"
Nick Lewyckyf7a3c502010-09-07 18:14:24 +000019#include "PTXTargetMachine.h"
Eric Christopher50880d02010-09-18 18:52:28 +000020#include "llvm/Support/raw_ostream.h"
21#include "llvm/ADT/SmallString.h"
Che-Liang Chioudf659632010-11-08 03:06:08 +000022#include "llvm/ADT/StringExtras.h"
23#include "llvm/ADT/Twine.h"
Nick Lewyckyf7a3c502010-09-07 18:14:24 +000024#include "llvm/CodeGen/AsmPrinter.h"
Eric Christopher50880d02010-09-18 18:52:28 +000025#include "llvm/CodeGen/MachineInstr.h"
26#include "llvm/MC/MCStreamer.h"
Che-Liang Chioudf659632010-11-08 03:06:08 +000027#include "llvm/MC/MCSymbol.h"
28#include "llvm/Target/TargetLoweringObjectFile.h"
Nick Lewyckyf7a3c502010-09-07 18:14:24 +000029#include "llvm/Target/TargetRegistry.h"
Che-Liang Chioudf659632010-11-08 03:06:08 +000030#include "llvm/Support/Debug.h"
31#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/raw_ostream.h"
Nick Lewyckyf7a3c502010-09-07 18:14:24 +000033
34using namespace llvm;
35
36namespace {
Che-Liang Chioudf659632010-11-08 03:06:08 +000037class PTXAsmPrinter : public AsmPrinter {
38public:
39 explicit PTXAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
40 : AsmPrinter(TM, Streamer) {}
Eric Christopher50880d02010-09-18 18:52:28 +000041
Che-Liang Chioudf659632010-11-08 03:06:08 +000042 const char *getPassName() const { return "PTX Assembly Printer"; }
Eric Christopher50880d02010-09-18 18:52:28 +000043
Che-Liang Chioudf659632010-11-08 03:06:08 +000044 virtual bool runOnMachineFunction(MachineFunction &MF);
Che-Liang Chioub48f2c22010-10-19 13:14:40 +000045
Che-Liang Chioudf659632010-11-08 03:06:08 +000046 virtual void EmitFunctionBodyStart();
47 virtual void EmitFunctionBodyEnd() { OutStreamer.EmitRawText(Twine("}")); }
48
49 virtual void EmitInstruction(const MachineInstr *MI);
50
51 void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
52
53 // autogen'd.
54 void printInstruction(const MachineInstr *MI, raw_ostream &OS);
55 static const char *getRegisterName(unsigned RegNo);
56
57private:
58 void EmitFunctionDeclaration();
59}; // class PTXAsmPrinter
Nick Lewyckyf7a3c502010-09-07 18:14:24 +000060} // namespace
61
Che-Liang Chioudf659632010-11-08 03:06:08 +000062static const char PARAM_PREFIX[] = "__param_";
63
64static const char *getRegisterTypeName(unsigned RegNo){
65#define TEST_REGCLS(cls, clsstr) \
66 if (PTX::cls ## RegisterClass->contains(RegNo)) return # clsstr;
67 TEST_REGCLS(RRegs32, .s32);
68 TEST_REGCLS(Preds, .pred);
69#undef TEST_REGCLS
70
71 llvm_unreachable("Not in any register class!");
72 return NULL;
73}
74
75bool PTXAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
76 SetupMachineFunction(MF);
77 EmitFunctionDeclaration();
78 EmitFunctionBody();
79 return false;
80}
81
82void PTXAsmPrinter::EmitFunctionBodyStart() {
83 OutStreamer.EmitRawText(Twine("{"));
84
85 const PTXMachineFunctionInfo *MFI = MF->getInfo<PTXMachineFunctionInfo>();
86
87 // Print local variable definition
88 for (PTXMachineFunctionInfo::reg_iterator
89 i = MFI->localVarRegBegin(), e = MFI->localVarRegEnd(); i != e; ++ i) {
90 unsigned reg = *i;
91
92 std::string def = "\t.reg ";
93 def += getRegisterTypeName(reg);
94 def += ' ';
95 def += getRegisterName(reg);
96 def += ';';
97 OutStreamer.EmitRawText(Twine(def));
98 }
99}
100
Eric Christopher50880d02010-09-18 18:52:28 +0000101void PTXAsmPrinter::EmitInstruction(const MachineInstr *MI) {
102 SmallString<128> str;
Che-Liang Chioub48f2c22010-10-19 13:14:40 +0000103 raw_svector_ostream OS(str);
104 printInstruction(MI, OS);
105 OS << ';';
106 OutStreamer.EmitRawText(OS.str());
107}
108
109void PTXAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
110 raw_ostream &OS) {
111 const MachineOperand &MO = MI->getOperand(opNum);
112
113 switch (MO.getType()) {
114 default:
115 llvm_unreachable("<unknown operand type>");
116 break;
117 case MachineOperand::MO_Register:
118 OS << getRegisterName(MO.getReg());
119 break;
120 case MachineOperand::MO_Immediate:
121 OS << (int) MO.getImm();
122 break;
123 }
Eric Christopher50880d02010-09-18 18:52:28 +0000124}
125
Che-Liang Chioudf659632010-11-08 03:06:08 +0000126void PTXAsmPrinter::EmitFunctionDeclaration() {
127 // The function label could have already been emitted if two symbols end up
128 // conflicting due to asm renaming. Detect this and emit an error.
129 if (!CurrentFnSym->isUndefined()) {
130 report_fatal_error("'" + Twine(CurrentFnSym->getName()) +
131 "' label emitted multiple times to assembly file");
132 return;
133 }
134
135 const PTXMachineFunctionInfo *MFI = MF->getInfo<PTXMachineFunctionInfo>();
136 const bool isKernel = MFI->isKernel();
137 unsigned reg;
138
139 std::string decl = isKernel ? ".entry" : ".func";
140
141 // Print return register
142 reg = MFI->retReg();
143 if (!isKernel && reg != PTX::NoRegister) {
144 decl += " (.reg "; // FIXME: could it return in .param space?
145 decl += getRegisterTypeName(reg);
146 decl += " ";
147 decl += getRegisterName(reg);
148 decl += ")";
149 }
150
151 // Print function name
152 decl += " ";
153 decl += CurrentFnSym->getName().str();
154
155 // Print parameter list
156 if (!MFI->argRegEmpty()) {
157 decl += " (";
158 if (isKernel) {
159 for (int i = 0, e = MFI->getNumArg(); i != e; ++i) {
160 if (i != 0)
161 decl += ", ";
162 decl += ".param .s32 "; // TODO: param's type
163 decl += PARAM_PREFIX;
164 decl += utostr(i + 1);
165 }
166 } else {
167 for (PTXMachineFunctionInfo::reg_iterator
168 i = MFI->argRegBegin(), e = MFI->argRegEnd(), b = i; i != e; ++i) {
169 reg = *i;
170 assert(reg != PTX::NoRegister && "Not a valid register!");
171 if (i != b)
172 decl += ", ";
173 decl += ".reg ";
174 decl += getRegisterTypeName(reg);
175 decl += " ";
176 decl += getRegisterName(reg);
177 }
178 }
179 decl += ")";
180 }
181
182 OutStreamer.EmitRawText(Twine(decl));
183}
184
Eric Christopher50880d02010-09-18 18:52:28 +0000185#include "PTXGenAsmWriter.inc"
186
Nick Lewyckyf7a3c502010-09-07 18:14:24 +0000187// Force static initialization.
Eric Christopher50880d02010-09-18 18:52:28 +0000188extern "C" void LLVMInitializePTXAsmPrinter() {
Nick Lewyckyf7a3c502010-09-07 18:14:24 +0000189 RegisterAsmPrinter<PTXAsmPrinter> X(ThePTXTarget);
190}