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