• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PTXInstPrinter(const MCAsmInfo & MAI,const MCSubtargetInfo & STI)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 
getOpcodeName(unsigned Opcode) const36 StringRef PTXInstPrinter::getOpcodeName(unsigned Opcode) const {
37   return getInstructionName(Opcode);
38 }
39 
printRegName(raw_ostream & OS,unsigned RegNo) const40 void PTXInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
41   OS << getRegisterName(RegNo);
42 }
43 
printInst(const MCInst * MI,raw_ostream & O,StringRef Annot)44 void PTXInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
45                                StringRef Annot) {
46   printPredicate(MI, O);
47   switch (MI->getOpcode()) {
48   default:
49     printInstruction(MI, O);
50     break;
51   case PTX::CALL:
52     printCall(MI, O);
53   }
54   O << ";";
55   printAnnotation(O, Annot);
56 }
57 
printPredicate(const MCInst * MI,raw_ostream & O)58 void PTXInstPrinter::printPredicate(const MCInst *MI, raw_ostream &O) {
59   // The last two operands are the predicate operands
60   int RegIndex;
61   int OpIndex;
62 
63   if (MI->getOpcode() == PTX::CALL) {
64     RegIndex = 0;
65     OpIndex  = 1;
66   } else {
67     RegIndex = MI->getNumOperands()-2;
68     OpIndex = MI->getNumOperands()-1;
69   }
70 
71   int PredOp = MI->getOperand(OpIndex).getImm();
72   if (PredOp == PTXPredicate::None)
73     return;
74 
75   if (PredOp == PTXPredicate::Negate)
76     O << '!';
77   else
78     O << '@';
79 
80   printOperand(MI, RegIndex, O);
81 }
82 
printCall(const MCInst * MI,raw_ostream & O)83 void PTXInstPrinter::printCall(const MCInst *MI, raw_ostream &O) {
84   O << "\tcall.uni\t";
85   // The first two operands are the predicate slot
86   unsigned Index = 2;
87   unsigned NumRets = MI->getOperand(Index++).getImm();
88 
89   if (NumRets > 0) {
90     O << "(";
91     printOperand(MI, Index++, O);
92     for (unsigned i = 1; i < NumRets; ++i) {
93       O << ", ";
94       printOperand(MI, Index++, O);
95     }
96     O << "), ";
97   }
98 
99   O << *(MI->getOperand(Index++).getExpr()) << ", (";
100 
101   unsigned NumArgs = MI->getOperand(Index++).getImm();
102   if (NumArgs > 0) {
103     printOperand(MI, Index++, O);
104     for (unsigned i = 1; i < NumArgs; ++i) {
105       O << ", ";
106       printOperand(MI, Index++, O);
107     }
108   }
109   O << ")";
110 }
111 
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)112 void PTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
113                                   raw_ostream &O) {
114   const MCOperand &Op = MI->getOperand(OpNo);
115   if (Op.isImm()) {
116     O << Op.getImm();
117   } else if (Op.isFPImm()) {
118     double Imm = Op.getFPImm();
119     APFloat FPImm(Imm);
120     APInt FPIntImm = FPImm.bitcastToAPInt();
121     O << "0D";
122     // PTX requires us to output the full 64 bits, even if the number is zero
123     if (FPIntImm.getZExtValue() > 0) {
124       O << FPIntImm.toString(16, false);
125     } else {
126       O << "0000000000000000";
127     }
128   } else {
129     assert(Op.isExpr() && "unknown operand kind in printOperand");
130     const MCExpr *Expr = Op.getExpr();
131     if (const MCSymbolRefExpr *SymRefExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
132       const MCSymbol &Sym = SymRefExpr->getSymbol();
133       O << Sym.getName();
134     } else {
135       O << *Op.getExpr();
136     }
137   }
138 }
139 
printMemOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)140 void PTXInstPrinter::printMemOperand(const MCInst *MI, unsigned OpNo,
141                                      raw_ostream &O) {
142   // By definition, operand OpNo+1 is an i32imm
143   const MCOperand &Op2 = MI->getOperand(OpNo+1);
144   printOperand(MI, OpNo, O);
145   if (Op2.getImm() == 0)
146     return; // don't print "+0"
147   O << "+" << Op2.getImm();
148 }
149 
printRoundingMode(const MCInst * MI,unsigned OpNo,raw_ostream & O)150 void PTXInstPrinter::printRoundingMode(const MCInst *MI, unsigned OpNo,
151                                        raw_ostream &O) {
152   const MCOperand &Op = MI->getOperand(OpNo);
153   assert (Op.isImm() && "Rounding modes must be immediate values");
154   switch (Op.getImm()) {
155   default:
156     llvm_unreachable("Unknown rounding mode!");
157   case PTXRoundingMode::RndDefault:
158     llvm_unreachable("FP rounding-mode pass did not handle instruction!");
159     break;
160   case PTXRoundingMode::RndNone:
161     // Do not print anything.
162     break;
163   case PTXRoundingMode::RndNearestEven:
164     O << ".rn";
165     break;
166   case PTXRoundingMode::RndTowardsZero:
167     O << ".rz";
168     break;
169   case PTXRoundingMode::RndNegInf:
170     O << ".rm";
171     break;
172   case PTXRoundingMode::RndPosInf:
173     O << ".rp";
174     break;
175   case PTXRoundingMode::RndApprox:
176     O << ".approx";
177     break;
178   case PTXRoundingMode::RndNearestEvenInt:
179     O << ".rni";
180     break;
181   case PTXRoundingMode::RndTowardsZeroInt:
182     O << ".rzi";
183     break;
184   case PTXRoundingMode::RndNegInfInt:
185     O << ".rmi";
186     break;
187   case PTXRoundingMode::RndPosInfInt:
188     O << ".rpi";
189     break;
190   }
191 }
192 
193