NVPTXInstPrinter.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. //===-- NVPTXInstPrinter.cpp - PTX assembly instruction printing ----------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // Print MCInst instructions to .ptx format.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "MCTargetDesc/NVPTXInstPrinter.h"
  13. #include "MCTargetDesc/NVPTXBaseInfo.h"
  14. #include "NVPTX.h"
  15. #include "llvm/MC/MCExpr.h"
  16. #include "llvm/MC/MCInst.h"
  17. #include "llvm/MC/MCInstrInfo.h"
  18. #include "llvm/MC/MCSubtargetInfo.h"
  19. #include "llvm/MC/MCSymbol.h"
  20. #include "llvm/Support/ErrorHandling.h"
  21. #include "llvm/Support/FormattedStream.h"
  22. #include <cctype>
  23. using namespace llvm;
  24. #define DEBUG_TYPE "asm-printer"
  25. #include "NVPTXGenAsmWriter.inc"
  26. NVPTXInstPrinter::NVPTXInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
  27. const MCRegisterInfo &MRI)
  28. : MCInstPrinter(MAI, MII, MRI) {}
  29. void NVPTXInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const {
  30. // Decode the virtual register
  31. // Must be kept in sync with NVPTXAsmPrinter::encodeVirtualRegister
  32. unsigned RCId = (Reg.id() >> 28);
  33. switch (RCId) {
  34. default: report_fatal_error("Bad virtual register encoding");
  35. case 0:
  36. // This is actually a physical register, so defer to the autogenerated
  37. // register printer
  38. OS << getRegisterName(Reg);
  39. return;
  40. case 1:
  41. OS << "%p";
  42. break;
  43. case 2:
  44. OS << "%rs";
  45. break;
  46. case 3:
  47. OS << "%r";
  48. break;
  49. case 4:
  50. OS << "%rd";
  51. break;
  52. case 5:
  53. OS << "%f";
  54. break;
  55. case 6:
  56. OS << "%fd";
  57. break;
  58. case 7:
  59. OS << "%h";
  60. break;
  61. case 8:
  62. OS << "%hh";
  63. break;
  64. }
  65. unsigned VReg = Reg.id() & 0x0FFFFFFF;
  66. OS << VReg;
  67. }
  68. void NVPTXInstPrinter::printInst(const MCInst *MI, uint64_t Address,
  69. StringRef Annot, const MCSubtargetInfo &STI,
  70. raw_ostream &OS) {
  71. printInstruction(MI, Address, OS);
  72. // Next always print the annotation.
  73. printAnnotation(OS, Annot);
  74. }
  75. void NVPTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
  76. raw_ostream &O) {
  77. const MCOperand &Op = MI->getOperand(OpNo);
  78. if (Op.isReg()) {
  79. unsigned Reg = Op.getReg();
  80. printRegName(O, Reg);
  81. } else if (Op.isImm()) {
  82. O << markup("<imm:") << formatImm(Op.getImm()) << markup(">");
  83. } else {
  84. assert(Op.isExpr() && "Unknown operand kind in printOperand");
  85. Op.getExpr()->print(O, &MAI);
  86. }
  87. }
  88. void NVPTXInstPrinter::printCvtMode(const MCInst *MI, int OpNum, raw_ostream &O,
  89. const char *Modifier) {
  90. const MCOperand &MO = MI->getOperand(OpNum);
  91. int64_t Imm = MO.getImm();
  92. if (strcmp(Modifier, "ftz") == 0) {
  93. // FTZ flag
  94. if (Imm & NVPTX::PTXCvtMode::FTZ_FLAG)
  95. O << ".ftz";
  96. } else if (strcmp(Modifier, "sat") == 0) {
  97. // SAT flag
  98. if (Imm & NVPTX::PTXCvtMode::SAT_FLAG)
  99. O << ".sat";
  100. } else if (strcmp(Modifier, "relu") == 0) {
  101. // RELU flag
  102. if (Imm & NVPTX::PTXCvtMode::RELU_FLAG)
  103. O << ".relu";
  104. } else if (strcmp(Modifier, "base") == 0) {
  105. // Default operand
  106. switch (Imm & NVPTX::PTXCvtMode::BASE_MASK) {
  107. default:
  108. return;
  109. case NVPTX::PTXCvtMode::NONE:
  110. break;
  111. case NVPTX::PTXCvtMode::RNI:
  112. O << ".rni";
  113. break;
  114. case NVPTX::PTXCvtMode::RZI:
  115. O << ".rzi";
  116. break;
  117. case NVPTX::PTXCvtMode::RMI:
  118. O << ".rmi";
  119. break;
  120. case NVPTX::PTXCvtMode::RPI:
  121. O << ".rpi";
  122. break;
  123. case NVPTX::PTXCvtMode::RN:
  124. O << ".rn";
  125. break;
  126. case NVPTX::PTXCvtMode::RZ:
  127. O << ".rz";
  128. break;
  129. case NVPTX::PTXCvtMode::RM:
  130. O << ".rm";
  131. break;
  132. case NVPTX::PTXCvtMode::RP:
  133. O << ".rp";
  134. break;
  135. case NVPTX::PTXCvtMode::RNA:
  136. O << ".rna";
  137. break;
  138. }
  139. } else {
  140. llvm_unreachable("Invalid conversion modifier");
  141. }
  142. }
  143. void NVPTXInstPrinter::printCmpMode(const MCInst *MI, int OpNum, raw_ostream &O,
  144. const char *Modifier) {
  145. const MCOperand &MO = MI->getOperand(OpNum);
  146. int64_t Imm = MO.getImm();
  147. if (strcmp(Modifier, "ftz") == 0) {
  148. // FTZ flag
  149. if (Imm & NVPTX::PTXCmpMode::FTZ_FLAG)
  150. O << ".ftz";
  151. } else if (strcmp(Modifier, "base") == 0) {
  152. switch (Imm & NVPTX::PTXCmpMode::BASE_MASK) {
  153. default:
  154. return;
  155. case NVPTX::PTXCmpMode::EQ:
  156. O << ".eq";
  157. break;
  158. case NVPTX::PTXCmpMode::NE:
  159. O << ".ne";
  160. break;
  161. case NVPTX::PTXCmpMode::LT:
  162. O << ".lt";
  163. break;
  164. case NVPTX::PTXCmpMode::LE:
  165. O << ".le";
  166. break;
  167. case NVPTX::PTXCmpMode::GT:
  168. O << ".gt";
  169. break;
  170. case NVPTX::PTXCmpMode::GE:
  171. O << ".ge";
  172. break;
  173. case NVPTX::PTXCmpMode::LO:
  174. O << ".lo";
  175. break;
  176. case NVPTX::PTXCmpMode::LS:
  177. O << ".ls";
  178. break;
  179. case NVPTX::PTXCmpMode::HI:
  180. O << ".hi";
  181. break;
  182. case NVPTX::PTXCmpMode::HS:
  183. O << ".hs";
  184. break;
  185. case NVPTX::PTXCmpMode::EQU:
  186. O << ".equ";
  187. break;
  188. case NVPTX::PTXCmpMode::NEU:
  189. O << ".neu";
  190. break;
  191. case NVPTX::PTXCmpMode::LTU:
  192. O << ".ltu";
  193. break;
  194. case NVPTX::PTXCmpMode::LEU:
  195. O << ".leu";
  196. break;
  197. case NVPTX::PTXCmpMode::GTU:
  198. O << ".gtu";
  199. break;
  200. case NVPTX::PTXCmpMode::GEU:
  201. O << ".geu";
  202. break;
  203. case NVPTX::PTXCmpMode::NUM:
  204. O << ".num";
  205. break;
  206. case NVPTX::PTXCmpMode::NotANumber:
  207. O << ".nan";
  208. break;
  209. }
  210. } else {
  211. llvm_unreachable("Empty Modifier");
  212. }
  213. }
  214. void NVPTXInstPrinter::printLdStCode(const MCInst *MI, int OpNum,
  215. raw_ostream &O, const char *Modifier) {
  216. if (Modifier) {
  217. const MCOperand &MO = MI->getOperand(OpNum);
  218. int Imm = (int) MO.getImm();
  219. if (!strcmp(Modifier, "volatile")) {
  220. if (Imm)
  221. O << ".volatile";
  222. } else if (!strcmp(Modifier, "addsp")) {
  223. switch (Imm) {
  224. case NVPTX::PTXLdStInstCode::GLOBAL:
  225. O << ".global";
  226. break;
  227. case NVPTX::PTXLdStInstCode::SHARED:
  228. O << ".shared";
  229. break;
  230. case NVPTX::PTXLdStInstCode::LOCAL:
  231. O << ".local";
  232. break;
  233. case NVPTX::PTXLdStInstCode::PARAM:
  234. O << ".param";
  235. break;
  236. case NVPTX::PTXLdStInstCode::CONSTANT:
  237. O << ".const";
  238. break;
  239. case NVPTX::PTXLdStInstCode::GENERIC:
  240. break;
  241. default:
  242. llvm_unreachable("Wrong Address Space");
  243. }
  244. } else if (!strcmp(Modifier, "sign")) {
  245. if (Imm == NVPTX::PTXLdStInstCode::Signed)
  246. O << "s";
  247. else if (Imm == NVPTX::PTXLdStInstCode::Unsigned)
  248. O << "u";
  249. else if (Imm == NVPTX::PTXLdStInstCode::Untyped)
  250. O << "b";
  251. else if (Imm == NVPTX::PTXLdStInstCode::Float)
  252. O << "f";
  253. else
  254. llvm_unreachable("Unknown register type");
  255. } else if (!strcmp(Modifier, "vec")) {
  256. if (Imm == NVPTX::PTXLdStInstCode::V2)
  257. O << ".v2";
  258. else if (Imm == NVPTX::PTXLdStInstCode::V4)
  259. O << ".v4";
  260. } else
  261. llvm_unreachable("Unknown Modifier");
  262. } else
  263. llvm_unreachable("Empty Modifier");
  264. }
  265. void NVPTXInstPrinter::printMmaCode(const MCInst *MI, int OpNum, raw_ostream &O,
  266. const char *Modifier) {
  267. const MCOperand &MO = MI->getOperand(OpNum);
  268. int Imm = (int)MO.getImm();
  269. if (Modifier == nullptr || strcmp(Modifier, "version") == 0) {
  270. O << Imm; // Just print out PTX version
  271. } else if (strcmp(Modifier, "aligned") == 0) {
  272. // PTX63 requires '.aligned' in the name of the instruction.
  273. if (Imm >= 63)
  274. O << ".aligned";
  275. } else
  276. llvm_unreachable("Unknown Modifier");
  277. }
  278. void NVPTXInstPrinter::printMemOperand(const MCInst *MI, int OpNum,
  279. raw_ostream &O, const char *Modifier) {
  280. printOperand(MI, OpNum, O);
  281. if (Modifier && !strcmp(Modifier, "add")) {
  282. O << ", ";
  283. printOperand(MI, OpNum + 1, O);
  284. } else {
  285. if (MI->getOperand(OpNum + 1).isImm() &&
  286. MI->getOperand(OpNum + 1).getImm() == 0)
  287. return; // don't print ',0' or '+0'
  288. O << "+";
  289. printOperand(MI, OpNum + 1, O);
  290. }
  291. }
  292. void NVPTXInstPrinter::printProtoIdent(const MCInst *MI, int OpNum,
  293. raw_ostream &O, const char *Modifier) {
  294. const MCOperand &Op = MI->getOperand(OpNum);
  295. assert(Op.isExpr() && "Call prototype is not an MCExpr?");
  296. const MCExpr *Expr = Op.getExpr();
  297. const MCSymbol &Sym = cast<MCSymbolRefExpr>(Expr)->getSymbol();
  298. O << Sym.getName();
  299. }