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 250