LLVM 19.0.0git
NVPTXInstPrinter.cpp
Go to the documentation of this file.
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
15#include "NVPTX.h"
16#include "llvm/MC/MCExpr.h"
17#include "llvm/MC/MCInst.h"
18#include "llvm/MC/MCInstrInfo.h"
20#include "llvm/MC/MCSymbol.h"
23#include <cctype>
24using namespace llvm;
25
26#define DEBUG_TYPE "asm-printer"
27
28#include "NVPTXGenAsmWriter.inc"
29
31 const MCRegisterInfo &MRI)
32 : MCInstPrinter(MAI, MII, MRI) {}
33
35 // Decode the virtual register
36 // Must be kept in sync with NVPTXAsmPrinter::encodeVirtualRegister
37 unsigned RCId = (Reg.id() >> 28);
38 switch (RCId) {
39 default: report_fatal_error("Bad virtual register encoding");
40 case 0:
41 // This is actually a physical register, so defer to the autogenerated
42 // register printer
43 OS << getRegisterName(Reg);
44 return;
45 case 1:
46 OS << "%p";
47 break;
48 case 2:
49 OS << "%rs";
50 break;
51 case 3:
52 OS << "%r";
53 break;
54 case 4:
55 OS << "%rd";
56 break;
57 case 5:
58 OS << "%f";
59 break;
60 case 6:
61 OS << "%fd";
62 break;
63 }
64
65 unsigned VReg = Reg.id() & 0x0FFFFFFF;
66 OS << VReg;
67}
68
70 StringRef Annot, const MCSubtargetInfo &STI,
71 raw_ostream &OS) {
73
74 // Next always print the annotation.
75 printAnnotation(OS, Annot);
76}
77
78void NVPTXInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
79 raw_ostream &O) {
80 const MCOperand &Op = MI->getOperand(OpNo);
81 if (Op.isReg()) {
82 unsigned Reg = Op.getReg();
83 printRegName(O, Reg);
84 } else if (Op.isImm()) {
85 markup(O, Markup::Immediate) << formatImm(Op.getImm());
86 } else {
87 assert(Op.isExpr() && "Unknown operand kind in printOperand");
88 Op.getExpr()->print(O, &MAI);
89 }
90}
91
93 const char *Modifier) {
94 const MCOperand &MO = MI->getOperand(OpNum);
95 int64_t Imm = MO.getImm();
96
97 if (strcmp(Modifier, "ftz") == 0) {
98 // FTZ flag
100 O << ".ftz";
101 } else if (strcmp(Modifier, "sat") == 0) {
102 // SAT flag
104 O << ".sat";
105 } else if (strcmp(Modifier, "relu") == 0) {
106 // RELU flag
108 O << ".relu";
109 } else if (strcmp(Modifier, "base") == 0) {
110 // Default operand
111 switch (Imm & NVPTX::PTXCvtMode::BASE_MASK) {
112 default:
113 return;
115 break;
117 O << ".rni";
118 break;
120 O << ".rzi";
121 break;
123 O << ".rmi";
124 break;
126 O << ".rpi";
127 break;
129 O << ".rn";
130 break;
132 O << ".rz";
133 break;
135 O << ".rm";
136 break;
138 O << ".rp";
139 break;
141 O << ".rna";
142 break;
143 }
144 } else {
145 llvm_unreachable("Invalid conversion modifier");
146 }
147}
148
150 const char *Modifier) {
151 const MCOperand &MO = MI->getOperand(OpNum);
152 int64_t Imm = MO.getImm();
153
154 if (strcmp(Modifier, "ftz") == 0) {
155 // FTZ flag
157 O << ".ftz";
158 } else if (strcmp(Modifier, "base") == 0) {
159 switch (Imm & NVPTX::PTXCmpMode::BASE_MASK) {
160 default:
161 return;
163 O << ".eq";
164 break;
166 O << ".ne";
167 break;
169 O << ".lt";
170 break;
172 O << ".le";
173 break;
175 O << ".gt";
176 break;
178 O << ".ge";
179 break;
181 O << ".lo";
182 break;
184 O << ".ls";
185 break;
187 O << ".hi";
188 break;
190 O << ".hs";
191 break;
193 O << ".equ";
194 break;
196 O << ".neu";
197 break;
199 O << ".ltu";
200 break;
202 O << ".leu";
203 break;
205 O << ".gtu";
206 break;
208 O << ".geu";
209 break;
211 O << ".num";
212 break;
214 O << ".nan";
215 break;
216 }
217 } else {
218 llvm_unreachable("Empty Modifier");
219 }
220}
221
223 raw_ostream &O, const char *Modifier) {
224 if (Modifier) {
225 const MCOperand &MO = MI->getOperand(OpNum);
226 int Imm = (int) MO.getImm();
227 if (!strcmp(Modifier, "volatile")) {
228 if (Imm)
229 O << ".volatile";
230 } else if (!strcmp(Modifier, "addsp")) {
231 switch (Imm) {
233 O << ".global";
234 break;
236 O << ".shared";
237 break;
239 O << ".local";
240 break;
242 O << ".param";
243 break;
245 O << ".const";
246 break;
248 break;
249 default:
250 llvm_unreachable("Wrong Address Space");
251 }
252 } else if (!strcmp(Modifier, "sign")) {
254 O << "s";
255 else if (Imm == NVPTX::PTXLdStInstCode::Unsigned)
256 O << "u";
257 else if (Imm == NVPTX::PTXLdStInstCode::Untyped)
258 O << "b";
259 else if (Imm == NVPTX::PTXLdStInstCode::Float)
260 O << "f";
261 else
262 llvm_unreachable("Unknown register type");
263 } else if (!strcmp(Modifier, "vec")) {
265 O << ".v2";
266 else if (Imm == NVPTX::PTXLdStInstCode::V4)
267 O << ".v4";
268 } else
269 llvm_unreachable("Unknown Modifier");
270 } else
271 llvm_unreachable("Empty Modifier");
272}
273
275 const char *Modifier) {
276 const MCOperand &MO = MI->getOperand(OpNum);
277 int Imm = (int)MO.getImm();
278 if (Modifier == nullptr || strcmp(Modifier, "version") == 0) {
279 O << Imm; // Just print out PTX version
280 } else if (strcmp(Modifier, "aligned") == 0) {
281 // PTX63 requires '.aligned' in the name of the instruction.
282 if (Imm >= 63)
283 O << ".aligned";
284 } else
285 llvm_unreachable("Unknown Modifier");
286}
287
289 raw_ostream &O, const char *Modifier) {
290 printOperand(MI, OpNum, O);
291
292 if (Modifier && !strcmp(Modifier, "add")) {
293 O << ", ";
294 printOperand(MI, OpNum + 1, O);
295 } else {
296 if (MI->getOperand(OpNum + 1).isImm() &&
297 MI->getOperand(OpNum + 1).getImm() == 0)
298 return; // don't print ',0' or '+0'
299 O << "+";
300 printOperand(MI, OpNum + 1, O);
301 }
302}
303
305 raw_ostream &O, const char *Modifier) {
306 const MCOperand &Op = MI->getOperand(OpNum);
307 assert(Op.isExpr() && "Call prototype is not an MCExpr?");
308 const MCExpr *Expr = Op.getExpr();
309 const MCSymbol &Sym = cast<MCSymbolRefExpr>(Expr)->getSymbol();
310 O << Sym.getName();
311}
312
314 raw_ostream &O, const char *Modifier) {
315 const MCOperand &MO = MI->getOperand(OpNum);
316 int64_t Imm = MO.getImm();
317
318 switch (Imm) {
319 default:
320 return;
322 break;
324 O << ".f4e";
325 break;
327 O << ".b4e";
328 break;
330 O << ".rc8";
331 break;
333 O << ".ecl";
334 break;
336 O << ".ecr";
337 break;
339 O << ".rc16";
340 break;
341 }
342}
unsigned const MachineRegisterInfo * MRI
Symbol * Sym
Definition: ELF_riscv.cpp:479
IRTranslator LLVM IR MI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This class represents an Operation in the Expression.
bool print(raw_ostream &OS, DIDumpOptions DumpOpts, const DWARFExpression *Expr, DWARFUnit *U) const
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition: MCAsmInfo.h:56
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
This is an instance of a target assembly language printer that converts an MCInst to valid target ass...
Definition: MCInstPrinter.h:45
WithMarkup markup(raw_ostream &OS, Markup M) const
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
const MCAsmInfo & MAI
Definition: MCInstPrinter.h:51
format_object< int64_t > formatImm(int64_t Value) const
Utility function to print immediates in decimal or hex.
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
int64_t getImm() const
Definition: MCInst.h:80
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
Generic base class for all target subtargets.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:40
void printCmpMode(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
void printMemOperand(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
void printCvtMode(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O)
void printLdStCode(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
void printProtoIdent(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
void printRegName(raw_ostream &OS, MCRegister Reg) const override
Print the assembler register name.
static const char * getRegisterName(MCRegister Reg)
void printPrmtMode(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, const MCSubtargetInfo &STI, raw_ostream &OS) override
Print the specified MCInst to the specified raw_ostream.
void printMmaCode(const MCInst *MI, int OpNum, raw_ostream &O, const char *Modifier=nullptr)
NVPTXInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI)
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167