LLVM API Documentation

NVPTXInstPrinter.cpp
Go to the documentation of this file.
00001 //===-- NVPTXInstPrinter.cpp - PTX assembly instruction printing ----------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // Print MCInst instructions to .ptx format.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "InstPrinter/NVPTXInstPrinter.h"
00015 #include "MCTargetDesc/NVPTXBaseInfo.h"
00016 #include "NVPTX.h"
00017 #include "llvm/MC/MCExpr.h"
00018 #include "llvm/MC/MCInst.h"
00019 #include "llvm/MC/MCInstrInfo.h"
00020 #include "llvm/MC/MCSubtargetInfo.h"
00021 #include "llvm/MC/MCSymbol.h"
00022 #include "llvm/Support/ErrorHandling.h"
00023 #include "llvm/Support/FormattedStream.h"
00024 #include <cctype>
00025 using namespace llvm;
00026 
00027 #define DEBUG_TYPE "asm-printer"
00028 
00029 #include "NVPTXGenAsmWriter.inc"
00030 
00031 
00032 NVPTXInstPrinter::NVPTXInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
00033                                    const MCRegisterInfo &MRI,
00034                                    const MCSubtargetInfo &STI)
00035   : MCInstPrinter(MAI, MII, MRI) {
00036   setAvailableFeatures(STI.getFeatureBits());
00037 }
00038 
00039 void NVPTXInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
00040   // Decode the virtual register
00041   // Must be kept in sync with NVPTXAsmPrinter::encodeVirtualRegister
00042   unsigned RCId = (RegNo >> 28);
00043   switch (RCId) {
00044   default: report_fatal_error("Bad virtual register encoding");
00045   case 0:
00046     // This is actually a physical register, so defer to the autogenerated
00047     // register printer
00048     OS << getRegisterName(RegNo);
00049     return;
00050   case 1:
00051     OS << "%p";
00052     break;
00053   case 2:
00054     OS << "%rs";
00055     break;
00056   case 3:
00057     OS << "%r";
00058     break;
00059   case 4:
00060     OS << "%rd";
00061     break;
00062   case 5:
00063     OS << "%f";
00064     break;
00065   case 6:
00066     OS << "%fd";
00067     break;
00068   }
00069 
00070   unsigned VReg = RegNo & 0x0FFFFFFF;
00071   OS << VReg;
00072 }
00073 
00074 void NVPTXInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
00075                                  StringRef Annot) {
00076   printInstruction(MI, OS);
00077 
00078   // Next always print the annotation.
00079   printAnnotation(OS, Annot);
00080 }
00081 
00082 void NVPTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
00083                                     raw_ostream &O) {
00084   const MCOperand &Op = MI->getOperand(OpNo);
00085   if (Op.isReg()) {
00086     unsigned Reg = Op.getReg();
00087     printRegName(O, Reg);
00088   } else if (Op.isImm()) {
00089     O << markup("<imm:") << formatImm(Op.getImm()) << markup(">");
00090   } else {
00091     assert(Op.isExpr() && "Unknown operand kind in printOperand");
00092     O << *Op.getExpr();
00093   }
00094 }
00095 
00096 void NVPTXInstPrinter::printCvtMode(const MCInst *MI, int OpNum, raw_ostream &O,
00097                                     const char *Modifier) {
00098   const MCOperand &MO = MI->getOperand(OpNum);
00099   int64_t Imm = MO.getImm();
00100 
00101   if (strcmp(Modifier, "ftz") == 0) {
00102     // FTZ flag
00103     if (Imm & NVPTX::PTXCvtMode::FTZ_FLAG)
00104       O << ".ftz";
00105   } else if (strcmp(Modifier, "sat") == 0) {
00106     // SAT flag
00107     if (Imm & NVPTX::PTXCvtMode::SAT_FLAG)
00108       O << ".sat";
00109   } else if (strcmp(Modifier, "base") == 0) {
00110     // Default operand
00111     switch (Imm & NVPTX::PTXCvtMode::BASE_MASK) {
00112     default:
00113       return;
00114     case NVPTX::PTXCvtMode::NONE:
00115       break;
00116     case NVPTX::PTXCvtMode::RNI:
00117       O << ".rni";
00118       break;
00119     case NVPTX::PTXCvtMode::RZI:
00120       O << ".rzi";
00121       break;
00122     case NVPTX::PTXCvtMode::RMI:
00123       O << ".rmi";
00124       break;
00125     case NVPTX::PTXCvtMode::RPI:
00126       O << ".rpi";
00127       break;
00128     case NVPTX::PTXCvtMode::RN:
00129       O << ".rn";
00130       break;
00131     case NVPTX::PTXCvtMode::RZ:
00132       O << ".rz";
00133       break;
00134     case NVPTX::PTXCvtMode::RM:
00135       O << ".rm";
00136       break;
00137     case NVPTX::PTXCvtMode::RP:
00138       O << ".rp";
00139       break;
00140     }
00141   } else {
00142     llvm_unreachable("Invalid conversion modifier");
00143   }
00144 }
00145 
00146 void NVPTXInstPrinter::printCmpMode(const MCInst *MI, int OpNum, raw_ostream &O,
00147                                     const char *Modifier) {
00148   const MCOperand &MO = MI->getOperand(OpNum);
00149   int64_t Imm = MO.getImm();
00150 
00151   if (strcmp(Modifier, "ftz") == 0) {
00152     // FTZ flag
00153     if (Imm & NVPTX::PTXCmpMode::FTZ_FLAG)
00154       O << ".ftz";
00155   } else if (strcmp(Modifier, "base") == 0) {
00156     switch (Imm & NVPTX::PTXCmpMode::BASE_MASK) {
00157     default:
00158       return;
00159     case NVPTX::PTXCmpMode::EQ:
00160       O << ".eq";
00161       break;
00162     case NVPTX::PTXCmpMode::NE:
00163       O << ".ne";
00164       break;
00165     case NVPTX::PTXCmpMode::LT:
00166       O << ".lt";
00167       break;
00168     case NVPTX::PTXCmpMode::LE:
00169       O << ".le";
00170       break;
00171     case NVPTX::PTXCmpMode::GT:
00172       O << ".gt";
00173       break;
00174     case NVPTX::PTXCmpMode::GE:
00175       O << ".ge";
00176       break;
00177     case NVPTX::PTXCmpMode::LO:
00178       O << ".lo";
00179       break;
00180     case NVPTX::PTXCmpMode::LS:
00181       O << ".ls";
00182       break;
00183     case NVPTX::PTXCmpMode::HI:
00184       O << ".hi";
00185       break;
00186     case NVPTX::PTXCmpMode::HS:
00187       O << ".hs";
00188       break;
00189     case NVPTX::PTXCmpMode::EQU:
00190       O << ".equ";
00191       break;
00192     case NVPTX::PTXCmpMode::NEU:
00193       O << ".neu";
00194       break;
00195     case NVPTX::PTXCmpMode::LTU:
00196       O << ".ltu";
00197       break;
00198     case NVPTX::PTXCmpMode::LEU:
00199       O << ".leu";
00200       break;
00201     case NVPTX::PTXCmpMode::GTU:
00202       O << ".gtu";
00203       break;
00204     case NVPTX::PTXCmpMode::GEU:
00205       O << ".geu";
00206       break;
00207     case NVPTX::PTXCmpMode::NUM:
00208       O << ".num";
00209       break;
00210     case NVPTX::PTXCmpMode::NotANumber:
00211       O << ".nan";
00212       break;
00213     }
00214   } else {
00215     llvm_unreachable("Empty Modifier");
00216   }
00217 }
00218 
00219 void NVPTXInstPrinter::printLdStCode(const MCInst *MI, int OpNum,
00220                                      raw_ostream &O, const char *Modifier) {
00221   if (Modifier) {
00222     const MCOperand &MO = MI->getOperand(OpNum);
00223     int Imm = (int) MO.getImm();
00224     if (!strcmp(Modifier, "volatile")) {
00225       if (Imm)
00226         O << ".volatile";
00227     } else if (!strcmp(Modifier, "addsp")) {
00228       switch (Imm) {
00229       case NVPTX::PTXLdStInstCode::GLOBAL:
00230         O << ".global";
00231         break;
00232       case NVPTX::PTXLdStInstCode::SHARED:
00233         O << ".shared";
00234         break;
00235       case NVPTX::PTXLdStInstCode::LOCAL:
00236         O << ".local";
00237         break;
00238       case NVPTX::PTXLdStInstCode::PARAM:
00239         O << ".param";
00240         break;
00241       case NVPTX::PTXLdStInstCode::CONSTANT:
00242         O << ".const";
00243         break;
00244       case NVPTX::PTXLdStInstCode::GENERIC:
00245         break;
00246       default:
00247         llvm_unreachable("Wrong Address Space");
00248       }
00249     } else if (!strcmp(Modifier, "sign")) {
00250       if (Imm == NVPTX::PTXLdStInstCode::Signed)
00251         O << "s";
00252       else if (Imm == NVPTX::PTXLdStInstCode::Unsigned)
00253         O << "u";
00254       else
00255         O << "f";
00256     } else if (!strcmp(Modifier, "vec")) {
00257       if (Imm == NVPTX::PTXLdStInstCode::V2)
00258         O << ".v2";
00259       else if (Imm == NVPTX::PTXLdStInstCode::V4)
00260         O << ".v4";
00261     } else
00262       llvm_unreachable("Unknown Modifier");
00263   } else
00264     llvm_unreachable("Empty Modifier");
00265 }
00266 
00267 void NVPTXInstPrinter::printMemOperand(const MCInst *MI, int OpNum,
00268                                        raw_ostream &O, const char *Modifier) {
00269   printOperand(MI, OpNum, O);
00270 
00271   if (Modifier && !strcmp(Modifier, "add")) {
00272     O << ", ";
00273     printOperand(MI, OpNum + 1, O);
00274   } else {
00275     if (MI->getOperand(OpNum + 1).isImm() &&
00276         MI->getOperand(OpNum + 1).getImm() == 0)
00277       return; // don't print ',0' or '+0'
00278     O << "+";
00279     printOperand(MI, OpNum + 1, O);
00280   }
00281 }
00282 
00283 void NVPTXInstPrinter::printProtoIdent(const MCInst *MI, int OpNum,
00284                                        raw_ostream &O, const char *Modifier) {
00285   const MCOperand &Op = MI->getOperand(OpNum);
00286   assert(Op.isExpr() && "Call prototype is not an MCExpr?");
00287   const MCExpr *Expr = Op.getExpr();
00288   const MCSymbol &Sym = cast<MCSymbolRefExpr>(Expr)->getSymbol();
00289   O << Sym.getName();
00290 }