Make MCRegisterInfo available to the the MCInstPrinter.
[oota-llvm.git] / lib / Target / PTX / InstPrinter / PTXInstPrinter.cpp
1 //===-- PTXInstPrinter.cpp - Convert PTX MCInst to assembly syntax --------===//
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 class prints a PTX MCInst to a .ptx file.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "asm-printer"
15 #include "PTXInstPrinter.h"
16 #include "MCTargetDesc/PTXBaseInfo.h"
17 #include "llvm/MC/MCAsmInfo.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCSymbol.h"
21 #include "llvm/ADT/StringExtras.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include "llvm/Support/raw_ostream.h"
24 using namespace llvm;
25
26 #define GET_INSTRUCTION_NAME
27 #include "PTXGenAsmWriter.inc"
28
29 PTXInstPrinter::PTXInstPrinter(const MCAsmInfo &MAI,
30                                const MCRegisterInfo &MRI,
31                                const MCSubtargetInfo &STI) :
32   MCInstPrinter(MAI, MRI) {
33   // Initialize the set of available features.
34   setAvailableFeatures(STI.getFeatureBits());
35 }
36
37 StringRef PTXInstPrinter::getOpcodeName(unsigned Opcode) const {
38   return getInstructionName(Opcode);
39 }
40
41 void PTXInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
42   // Decode the register number into type and offset
43   unsigned RegSpace  = RegNo & 0x7;
44   unsigned RegType   = (RegNo >> 3) & 0x7;
45   unsigned RegOffset = RegNo >> 6;
46
47   // Print the register
48   OS << "%";
49
50   switch (RegSpace) {
51   default:
52     llvm_unreachable("Unknown register space!");
53   case PTXRegisterSpace::Reg:
54     switch (RegType) {
55     default:
56       llvm_unreachable("Unknown register type!");
57     case PTXRegisterType::Pred:
58       OS << "p";
59       break;
60     case PTXRegisterType::B16:
61       OS << "rh";
62       break;
63     case PTXRegisterType::B32:
64       OS << "r";
65       break;
66     case PTXRegisterType::B64:
67       OS << "rd";
68       break;
69     case PTXRegisterType::F32:
70       OS << "f";
71       break;
72     case PTXRegisterType::F64:
73       OS << "fd";
74       break;
75     }
76     break;
77   case PTXRegisterSpace::Return:
78     OS << "ret";
79     break;
80   case PTXRegisterSpace::Argument:
81     OS << "arg";
82     break;
83   }
84
85   OS << RegOffset;
86 }
87
88 void PTXInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
89                                StringRef Annot) {
90   printPredicate(MI, O);
91   switch (MI->getOpcode()) {
92   default:
93     printInstruction(MI, O);
94     break;
95   case PTX::CALL:
96     printCall(MI, O);
97   }
98   O << ";";
99   printAnnotation(O, Annot);
100 }
101
102 void PTXInstPrinter::printPredicate(const MCInst *MI, raw_ostream &O) {
103   // The last two operands are the predicate operands
104   int RegIndex;
105   int OpIndex;
106
107   if (MI->getOpcode() == PTX::CALL) {
108     RegIndex = 0;
109     OpIndex  = 1;
110   } else {
111     RegIndex = MI->getNumOperands()-2;
112     OpIndex = MI->getNumOperands()-1;
113   }
114
115   int PredOp = MI->getOperand(OpIndex).getImm();
116   if (PredOp == PTXPredicate::None)
117     return;
118
119   if (PredOp == PTXPredicate::Negate)
120     O << '!';
121   else
122     O << '@';
123
124   printOperand(MI, RegIndex, O);
125 }
126
127 void PTXInstPrinter::printCall(const MCInst *MI, raw_ostream &O) {
128   O << "\tcall.uni\t";
129   // The first two operands are the predicate slot
130   unsigned Index = 2;
131   unsigned NumRets = MI->getOperand(Index++).getImm();
132
133   if (NumRets > 0) {
134     O << "(";
135     printOperand(MI, Index++, O);
136     for (unsigned i = 1; i < NumRets; ++i) {
137       O << ", ";
138       printOperand(MI, Index++, O);
139     }
140     O << "), ";
141   }
142
143   const MCExpr* Expr = MI->getOperand(Index++).getExpr();
144   unsigned NumArgs = MI->getOperand(Index++).getImm();
145   
146   // if the function call is to printf or puts, change to vprintf
147   if (const MCSymbolRefExpr *SymRefExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
148     const MCSymbol &Sym = SymRefExpr->getSymbol();
149     if (Sym.getName() == "printf" || Sym.getName() == "puts") {
150       O << "vprintf";
151     } else {
152       O << Sym.getName();
153     }
154   } else {
155     O << *Expr;
156   }
157   
158   O << ", (";
159
160   if (NumArgs > 0) {
161     printOperand(MI, Index++, O);
162     for (unsigned i = 1; i < NumArgs; ++i) {
163       O << ", ";
164       printOperand(MI, Index++, O);
165     }
166   }
167   O << ")";
168 }
169
170 void PTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
171                                   raw_ostream &O) {
172   const MCOperand &Op = MI->getOperand(OpNo);
173   if (Op.isImm()) {
174     O << Op.getImm();
175   } else if (Op.isFPImm()) {
176     double Imm = Op.getFPImm();
177     APFloat FPImm(Imm);
178     APInt FPIntImm = FPImm.bitcastToAPInt();
179     O << "0D";
180     // PTX requires us to output the full 64 bits, even if the number is zero
181     if (FPIntImm.getZExtValue() > 0) {
182       O << FPIntImm.toString(16, false);
183     } else {
184       O << "0000000000000000";
185     }
186   } else if (Op.isReg()) {
187     printRegName(O, Op.getReg());
188   } else {
189     assert(Op.isExpr() && "unknown operand kind in printOperand");
190     const MCExpr *Expr = Op.getExpr();
191     if (const MCSymbolRefExpr *SymRefExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
192       const MCSymbol &Sym = SymRefExpr->getSymbol();
193       O << Sym.getName();
194     } else {
195       O << *Op.getExpr();
196     }
197   }
198 }
199
200 void PTXInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
201                                      raw_ostream &O) {
202   // By definition, operand OpNo+1 is an i32imm
203   const MCOperand &Op2 = MI->getOperand(OpNo+1);
204   printOperand(MI, OpNo, O);
205   if (Op2.getImm() == 0)
206     return; // don't print "+0"
207   O << "+" << Op2.getImm();
208 }
209
210 void PTXInstPrinter::printRoundingMode(const MCInst *MI, unsigned OpNo,
211                                        raw_ostream &O) {
212   const MCOperand &Op = MI->getOperand(OpNo);
213   assert (Op.isImm() && "Rounding modes must be immediate values");
214   switch (Op.getImm()) {
215   default:
216     llvm_unreachable("Unknown rounding mode!");
217   case PTXRoundingMode::RndDefault:
218     llvm_unreachable("FP rounding-mode pass did not handle instruction!");
219   case PTXRoundingMode::RndNone:
220     // Do not print anything.
221     break;
222   case PTXRoundingMode::RndNearestEven:
223     O << ".rn";
224     break;
225   case PTXRoundingMode::RndTowardsZero:
226     O << ".rz";
227     break;
228   case PTXRoundingMode::RndNegInf:
229     O << ".rm";
230     break;
231   case PTXRoundingMode::RndPosInf:
232     O << ".rp";
233     break;
234   case PTXRoundingMode::RndApprox:
235     O << ".approx";
236     break;
237   case PTXRoundingMode::RndNearestEvenInt:
238     O << ".rni";
239     break;
240   case PTXRoundingMode::RndTowardsZeroInt:
241     O << ".rzi";
242     break;
243   case PTXRoundingMode::RndNegInfInt:
244     O << ".rmi";
245     break;
246   case PTXRoundingMode::RndPosInfInt:
247     O << ".rpi";
248     break;
249   }
250 }
251