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