1 //===-- SPIRVInstPrinter.cpp - Output SPIR-V MCInsts as ASM -----*- C++ -*-===//
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 // This class prints a SPIR-V MCInst to a .s file.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "SPIRVInstPrinter.h"
14 #include "SPIRV.h"
15 #include "SPIRVBaseInfo.h"
16 #include "llvm/CodeGen/Register.h"
17 #include "llvm/MC/MCAsmInfo.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCInstrInfo.h"
21 #include "llvm/MC/MCSymbol.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/FormattedStream.h"
25
26 using namespace llvm;
27
28 #define DEBUG_TYPE "asm-printer"
29
30 // Include the auto-generated portion of the assembly writer.
31 #include "SPIRVGenAsmWriter.inc"
32
printRemainingVariableOps(const MCInst * MI,unsigned StartIndex,raw_ostream & O,bool SkipFirstSpace,bool SkipImmediates)33 void SPIRVInstPrinter::printRemainingVariableOps(const MCInst *MI,
34 unsigned StartIndex,
35 raw_ostream &O,
36 bool SkipFirstSpace,
37 bool SkipImmediates) {
38 const unsigned NumOps = MI->getNumOperands();
39 for (unsigned i = StartIndex; i < NumOps; ++i) {
40 if (!SkipImmediates || !MI->getOperand(i).isImm()) {
41 if (!SkipFirstSpace || i != StartIndex)
42 O << ' ';
43 printOperand(MI, i, O);
44 }
45 }
46 }
47
printOpConstantVarOps(const MCInst * MI,unsigned StartIndex,raw_ostream & O)48 void SPIRVInstPrinter::printOpConstantVarOps(const MCInst *MI,
49 unsigned StartIndex,
50 raw_ostream &O) {
51 O << ' ';
52 if (MI->getNumOperands() - StartIndex == 2) { // Handle 64 bit literals.
53 uint64_t Imm = MI->getOperand(StartIndex).getImm();
54 Imm |= (MI->getOperand(StartIndex + 1).getImm() << 32);
55 O << Imm;
56 } else {
57 printRemainingVariableOps(MI, StartIndex, O, true, false);
58 }
59 }
60
recordOpExtInstImport(const MCInst * MI)61 void SPIRVInstPrinter::recordOpExtInstImport(const MCInst *MI) {
62 // TODO: insert {Reg, Set} into ExtInstSetIDs map.
63 }
64
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & OS)65 void SPIRVInstPrinter::printInst(const MCInst *MI, uint64_t Address,
66 StringRef Annot, const MCSubtargetInfo &STI,
67 raw_ostream &OS) {
68 const unsigned OpCode = MI->getOpcode();
69 printInstruction(MI, Address, OS);
70
71 if (OpCode == SPIRV::OpDecorate) {
72 printOpDecorate(MI, OS);
73 } else if (OpCode == SPIRV::OpExtInstImport) {
74 recordOpExtInstImport(MI);
75 } else if (OpCode == SPIRV::OpExtInst) {
76 printOpExtInst(MI, OS);
77 } else {
78 // Print any extra operands for variadic instructions.
79 MCInstrDesc MCDesc = MII.get(OpCode);
80 if (MCDesc.isVariadic()) {
81 const unsigned NumFixedOps = MCDesc.getNumOperands();
82 const unsigned LastFixedIndex = NumFixedOps - 1;
83 const int FirstVariableIndex = NumFixedOps;
84 if (NumFixedOps > 0 &&
85 MCDesc.OpInfo[LastFixedIndex].OperandType == MCOI::OPERAND_UNKNOWN) {
86 // For instructions where a custom type (not reg or immediate) comes as
87 // the last operand before the variable_ops. This is usually a StringImm
88 // operand, but there are a few other cases.
89 switch (OpCode) {
90 case SPIRV::OpTypeImage:
91 OS << ' ';
92 printAccessQualifier(MI, FirstVariableIndex, OS);
93 break;
94 case SPIRV::OpVariable:
95 OS << ' ';
96 printOperand(MI, FirstVariableIndex, OS);
97 break;
98 case SPIRV::OpEntryPoint: {
99 // Print the interface ID operands, skipping the name's string
100 // literal.
101 printRemainingVariableOps(MI, NumFixedOps, OS, false, true);
102 break;
103 }
104 case SPIRV::OpExecutionMode:
105 case SPIRV::OpExecutionModeId:
106 case SPIRV::OpLoopMerge: {
107 // Print any literals after the OPERAND_UNKNOWN argument normally.
108 printRemainingVariableOps(MI, NumFixedOps, OS);
109 break;
110 }
111 default:
112 break; // printStringImm has already been handled
113 }
114 } else {
115 // For instructions with no fixed ops or a reg/immediate as the final
116 // fixed operand, we can usually print the rest with "printOperand", but
117 // check for a few cases with custom types first.
118 switch (OpCode) {
119 case SPIRV::OpLoad:
120 case SPIRV::OpStore:
121 OS << ' ';
122 printMemoryOperand(MI, FirstVariableIndex, OS);
123 printRemainingVariableOps(MI, FirstVariableIndex + 1, OS);
124 break;
125 case SPIRV::OpImageSampleImplicitLod:
126 case SPIRV::OpImageSampleDrefImplicitLod:
127 case SPIRV::OpImageSampleProjImplicitLod:
128 case SPIRV::OpImageSampleProjDrefImplicitLod:
129 case SPIRV::OpImageFetch:
130 case SPIRV::OpImageGather:
131 case SPIRV::OpImageDrefGather:
132 case SPIRV::OpImageRead:
133 case SPIRV::OpImageWrite:
134 case SPIRV::OpImageSparseSampleImplicitLod:
135 case SPIRV::OpImageSparseSampleDrefImplicitLod:
136 case SPIRV::OpImageSparseSampleProjImplicitLod:
137 case SPIRV::OpImageSparseSampleProjDrefImplicitLod:
138 case SPIRV::OpImageSparseFetch:
139 case SPIRV::OpImageSparseGather:
140 case SPIRV::OpImageSparseDrefGather:
141 case SPIRV::OpImageSparseRead:
142 case SPIRV::OpImageSampleFootprintNV:
143 OS << ' ';
144 printImageOperand(MI, FirstVariableIndex, OS);
145 printRemainingVariableOps(MI, NumFixedOps + 1, OS);
146 break;
147 case SPIRV::OpCopyMemory:
148 case SPIRV::OpCopyMemorySized: {
149 const unsigned NumOps = MI->getNumOperands();
150 for (unsigned i = NumFixedOps; i < NumOps; ++i) {
151 OS << ' ';
152 printMemoryOperand(MI, i, OS);
153 if (MI->getOperand(i).getImm() &
154 static_cast<unsigned>(SPIRV::MemoryOperand::Aligned)) {
155 assert(i + 1 < NumOps && "Missing alignment operand");
156 OS << ' ';
157 printOperand(MI, i + 1, OS);
158 i += 1;
159 }
160 }
161 break;
162 }
163 case SPIRV::OpConstantI:
164 case SPIRV::OpConstantF:
165 printOpConstantVarOps(MI, NumFixedOps, OS);
166 break;
167 default:
168 printRemainingVariableOps(MI, NumFixedOps, OS);
169 break;
170 }
171 }
172 }
173 }
174
175 printAnnotation(OS, Annot);
176 }
177
printOpExtInst(const MCInst * MI,raw_ostream & O)178 void SPIRVInstPrinter::printOpExtInst(const MCInst *MI, raw_ostream &O) {
179 // The fixed operands have already been printed, so just need to decide what
180 // type of ExtInst operands to print based on the instruction set and number.
181 MCInstrDesc MCDesc = MII.get(MI->getOpcode());
182 unsigned NumFixedOps = MCDesc.getNumOperands();
183 const auto NumOps = MI->getNumOperands();
184 if (NumOps == NumFixedOps)
185 return;
186
187 O << ' ';
188
189 // TODO: implement special printing for OpenCLExtInst::vstor*.
190 printRemainingVariableOps(MI, NumFixedOps, O, true);
191 }
192
printOpDecorate(const MCInst * MI,raw_ostream & O)193 void SPIRVInstPrinter::printOpDecorate(const MCInst *MI, raw_ostream &O) {
194 // The fixed operands have already been printed, so just need to decide what
195 // type of decoration operands to print based on the Decoration type.
196 MCInstrDesc MCDesc = MII.get(MI->getOpcode());
197 unsigned NumFixedOps = MCDesc.getNumOperands();
198
199 if (NumFixedOps != MI->getNumOperands()) {
200 auto DecOp = MI->getOperand(NumFixedOps - 1);
201 auto Dec = static_cast<SPIRV::Decoration>(DecOp.getImm());
202
203 O << ' ';
204
205 switch (Dec) {
206 case SPIRV::Decoration::BuiltIn:
207 printBuiltIn(MI, NumFixedOps, O);
208 break;
209 case SPIRV::Decoration::UniformId:
210 printScope(MI, NumFixedOps, O);
211 break;
212 case SPIRV::Decoration::FuncParamAttr:
213 printFunctionParameterAttribute(MI, NumFixedOps, O);
214 break;
215 case SPIRV::Decoration::FPRoundingMode:
216 printFPRoundingMode(MI, NumFixedOps, O);
217 break;
218 case SPIRV::Decoration::FPFastMathMode:
219 printFPFastMathMode(MI, NumFixedOps, O);
220 break;
221 case SPIRV::Decoration::LinkageAttributes:
222 case SPIRV::Decoration::UserSemantic:
223 printStringImm(MI, NumFixedOps, O);
224 break;
225 default:
226 printRemainingVariableOps(MI, NumFixedOps, O, true);
227 break;
228 }
229 }
230 }
231
printExpr(const MCExpr * Expr,raw_ostream & O)232 static void printExpr(const MCExpr *Expr, raw_ostream &O) {
233 #ifndef NDEBUG
234 const MCSymbolRefExpr *SRE;
235
236 if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr))
237 SRE = cast<MCSymbolRefExpr>(BE->getLHS());
238 else
239 SRE = cast<MCSymbolRefExpr>(Expr);
240
241 MCSymbolRefExpr::VariantKind Kind = SRE->getKind();
242
243 assert(Kind == MCSymbolRefExpr::VK_None);
244 #endif
245 O << *Expr;
246 }
247
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O,const char * Modifier)248 void SPIRVInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
249 raw_ostream &O, const char *Modifier) {
250 assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
251 if (OpNo < MI->getNumOperands()) {
252 const MCOperand &Op = MI->getOperand(OpNo);
253 if (Op.isReg())
254 O << '%' << (Register::virtReg2Index(Op.getReg()) + 1);
255 else if (Op.isImm())
256 O << formatImm((int64_t)Op.getImm());
257 else if (Op.isDFPImm())
258 O << formatImm((double)Op.getDFPImm());
259 else if (Op.isExpr())
260 printExpr(Op.getExpr(), O);
261 else
262 llvm_unreachable("Unexpected operand type");
263 }
264 }
265
printStringImm(const MCInst * MI,unsigned OpNo,raw_ostream & O)266 void SPIRVInstPrinter::printStringImm(const MCInst *MI, unsigned OpNo,
267 raw_ostream &O) {
268 const unsigned NumOps = MI->getNumOperands();
269 unsigned StrStartIndex = OpNo;
270 while (StrStartIndex < NumOps) {
271 if (MI->getOperand(StrStartIndex).isReg())
272 break;
273
274 std::string Str = getSPIRVStringOperand(*MI, OpNo);
275 if (StrStartIndex != OpNo)
276 O << ' '; // Add a space if we're starting a new string/argument.
277 O << '"';
278 for (char c : Str) {
279 if (c == '"')
280 O.write('\\'); // Escape " characters (might break for complex UTF-8).
281 O.write(c);
282 }
283 O << '"';
284
285 unsigned numOpsInString = (Str.size() / 4) + 1;
286 StrStartIndex += numOpsInString;
287
288 // Check for final Op of "OpDecorate %x %stringImm %linkageAttribute".
289 if (MI->getOpcode() == SPIRV::OpDecorate &&
290 MI->getOperand(1).getImm() ==
291 static_cast<unsigned>(SPIRV::Decoration::LinkageAttributes)) {
292 O << ' ';
293 printLinkageType(MI, StrStartIndex, O);
294 break;
295 }
296 }
297 }
298
printExtInst(const MCInst * MI,unsigned OpNo,raw_ostream & O)299 void SPIRVInstPrinter::printExtInst(const MCInst *MI, unsigned OpNo,
300 raw_ostream &O) {
301 llvm_unreachable("Unimplemented printExtInst");
302 }
303
printCapability(const MCInst * MI,unsigned OpNo,raw_ostream & O)304 void SPIRVInstPrinter::printCapability(const MCInst *MI, unsigned OpNo,
305 raw_ostream &O) {
306 if (OpNo < MI->getNumOperands()) {
307 SPIRV::Capability e =
308 static_cast<SPIRV::Capability>(MI->getOperand(OpNo).getImm());
309 O << SPIRV::getCapabilityName(e);
310 }
311 }
312
printSourceLanguage(const MCInst * MI,unsigned OpNo,raw_ostream & O)313 void SPIRVInstPrinter::printSourceLanguage(const MCInst *MI, unsigned OpNo,
314 raw_ostream &O) {
315 if (OpNo < MI->getNumOperands()) {
316 SPIRV::SourceLanguage e =
317 static_cast<SPIRV::SourceLanguage>(MI->getOperand(OpNo).getImm());
318 O << SPIRV::getSourceLanguageName(e);
319 }
320 }
321
printExecutionModel(const MCInst * MI,unsigned OpNo,raw_ostream & O)322 void SPIRVInstPrinter::printExecutionModel(const MCInst *MI, unsigned OpNo,
323 raw_ostream &O) {
324 if (OpNo < MI->getNumOperands()) {
325 SPIRV::ExecutionModel e =
326 static_cast<SPIRV::ExecutionModel>(MI->getOperand(OpNo).getImm());
327 O << SPIRV::getExecutionModelName(e);
328 }
329 }
330
printAddressingModel(const MCInst * MI,unsigned OpNo,raw_ostream & O)331 void SPIRVInstPrinter::printAddressingModel(const MCInst *MI, unsigned OpNo,
332 raw_ostream &O) {
333 if (OpNo < MI->getNumOperands()) {
334 SPIRV::AddressingModel e =
335 static_cast<SPIRV::AddressingModel>(MI->getOperand(OpNo).getImm());
336 O << SPIRV::getAddressingModelName(e);
337 }
338 }
339
printMemoryModel(const MCInst * MI,unsigned OpNo,raw_ostream & O)340 void SPIRVInstPrinter::printMemoryModel(const MCInst *MI, unsigned OpNo,
341 raw_ostream &O) {
342 if (OpNo < MI->getNumOperands()) {
343 SPIRV::MemoryModel e =
344 static_cast<SPIRV::MemoryModel>(MI->getOperand(OpNo).getImm());
345 O << SPIRV::getMemoryModelName(e);
346 }
347 }
348
printExecutionMode(const MCInst * MI,unsigned OpNo,raw_ostream & O)349 void SPIRVInstPrinter::printExecutionMode(const MCInst *MI, unsigned OpNo,
350 raw_ostream &O) {
351 if (OpNo < MI->getNumOperands()) {
352 SPIRV::ExecutionMode e =
353 static_cast<SPIRV::ExecutionMode>(MI->getOperand(OpNo).getImm());
354 O << SPIRV::getExecutionModeName(e);
355 }
356 }
357
printStorageClass(const MCInst * MI,unsigned OpNo,raw_ostream & O)358 void SPIRVInstPrinter::printStorageClass(const MCInst *MI, unsigned OpNo,
359 raw_ostream &O) {
360 if (OpNo < MI->getNumOperands()) {
361 SPIRV::StorageClass e =
362 static_cast<SPIRV::StorageClass>(MI->getOperand(OpNo).getImm());
363 O << SPIRV::getStorageClassName(e);
364 }
365 }
366
printDim(const MCInst * MI,unsigned OpNo,raw_ostream & O)367 void SPIRVInstPrinter::printDim(const MCInst *MI, unsigned OpNo,
368 raw_ostream &O) {
369 if (OpNo < MI->getNumOperands()) {
370 SPIRV::Dim e = static_cast<SPIRV::Dim>(MI->getOperand(OpNo).getImm());
371 O << SPIRV::getDimName(e);
372 }
373 }
374
printSamplerAddressingMode(const MCInst * MI,unsigned OpNo,raw_ostream & O)375 void SPIRVInstPrinter::printSamplerAddressingMode(const MCInst *MI,
376 unsigned OpNo,
377 raw_ostream &O) {
378 if (OpNo < MI->getNumOperands()) {
379 SPIRV::SamplerAddressingMode e = static_cast<SPIRV::SamplerAddressingMode>(
380 MI->getOperand(OpNo).getImm());
381 O << SPIRV::getSamplerAddressingModeName(e);
382 }
383 }
384
printSamplerFilterMode(const MCInst * MI,unsigned OpNo,raw_ostream & O)385 void SPIRVInstPrinter::printSamplerFilterMode(const MCInst *MI, unsigned OpNo,
386 raw_ostream &O) {
387 if (OpNo < MI->getNumOperands()) {
388 SPIRV::SamplerFilterMode e =
389 static_cast<SPIRV::SamplerFilterMode>(MI->getOperand(OpNo).getImm());
390 O << SPIRV::getSamplerFilterModeName(e);
391 }
392 }
393
printImageFormat(const MCInst * MI,unsigned OpNo,raw_ostream & O)394 void SPIRVInstPrinter::printImageFormat(const MCInst *MI, unsigned OpNo,
395 raw_ostream &O) {
396 if (OpNo < MI->getNumOperands()) {
397 SPIRV::ImageFormat e =
398 static_cast<SPIRV::ImageFormat>(MI->getOperand(OpNo).getImm());
399 O << SPIRV::getImageFormatName(e);
400 }
401 }
402
printImageChannelOrder(const MCInst * MI,unsigned OpNo,raw_ostream & O)403 void SPIRVInstPrinter::printImageChannelOrder(const MCInst *MI, unsigned OpNo,
404 raw_ostream &O) {
405 if (OpNo < MI->getNumOperands()) {
406 SPIRV::ImageChannelOrder e =
407 static_cast<SPIRV::ImageChannelOrder>(MI->getOperand(OpNo).getImm());
408 O << SPIRV::getImageChannelOrderName(e);
409 }
410 }
411
printImageChannelDataType(const MCInst * MI,unsigned OpNo,raw_ostream & O)412 void SPIRVInstPrinter::printImageChannelDataType(const MCInst *MI,
413 unsigned OpNo,
414 raw_ostream &O) {
415 if (OpNo < MI->getNumOperands()) {
416 SPIRV::ImageChannelDataType e =
417 static_cast<SPIRV::ImageChannelDataType>(MI->getOperand(OpNo).getImm());
418 O << SPIRV::getImageChannelDataTypeName(e);
419 }
420 }
421
printImageOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)422 void SPIRVInstPrinter::printImageOperand(const MCInst *MI, unsigned OpNo,
423 raw_ostream &O) {
424 if (OpNo < MI->getNumOperands()) {
425 unsigned e = static_cast<unsigned>(MI->getOperand(OpNo).getImm());
426 O << SPIRV::getImageOperandName(e);
427 }
428 }
429
printFPFastMathMode(const MCInst * MI,unsigned OpNo,raw_ostream & O)430 void SPIRVInstPrinter::printFPFastMathMode(const MCInst *MI, unsigned OpNo,
431 raw_ostream &O) {
432 if (OpNo < MI->getNumOperands()) {
433 unsigned e = static_cast<unsigned>(MI->getOperand(OpNo).getImm());
434 O << SPIRV::getFPFastMathModeName(e);
435 }
436 }
437
printFPRoundingMode(const MCInst * MI,unsigned OpNo,raw_ostream & O)438 void SPIRVInstPrinter::printFPRoundingMode(const MCInst *MI, unsigned OpNo,
439 raw_ostream &O) {
440 if (OpNo < MI->getNumOperands()) {
441 SPIRV::FPRoundingMode e =
442 static_cast<SPIRV::FPRoundingMode>(MI->getOperand(OpNo).getImm());
443 O << SPIRV::getFPRoundingModeName(e);
444 }
445 }
446
printLinkageType(const MCInst * MI,unsigned OpNo,raw_ostream & O)447 void SPIRVInstPrinter::printLinkageType(const MCInst *MI, unsigned OpNo,
448 raw_ostream &O) {
449 if (OpNo < MI->getNumOperands()) {
450 SPIRV::LinkageType e =
451 static_cast<SPIRV::LinkageType>(MI->getOperand(OpNo).getImm());
452 O << SPIRV::getLinkageTypeName(e);
453 }
454 }
455
printAccessQualifier(const MCInst * MI,unsigned OpNo,raw_ostream & O)456 void SPIRVInstPrinter::printAccessQualifier(const MCInst *MI, unsigned OpNo,
457 raw_ostream &O) {
458 if (OpNo < MI->getNumOperands()) {
459 SPIRV::AccessQualifier e =
460 static_cast<SPIRV::AccessQualifier>(MI->getOperand(OpNo).getImm());
461 O << SPIRV::getAccessQualifierName(e);
462 }
463 }
464
printFunctionParameterAttribute(const MCInst * MI,unsigned OpNo,raw_ostream & O)465 void SPIRVInstPrinter::printFunctionParameterAttribute(const MCInst *MI,
466 unsigned OpNo,
467 raw_ostream &O) {
468 if (OpNo < MI->getNumOperands()) {
469 SPIRV::FunctionParameterAttribute e =
470 static_cast<SPIRV::FunctionParameterAttribute>(
471 MI->getOperand(OpNo).getImm());
472 O << SPIRV::getFunctionParameterAttributeName(e);
473 }
474 }
475
printDecoration(const MCInst * MI,unsigned OpNo,raw_ostream & O)476 void SPIRVInstPrinter::printDecoration(const MCInst *MI, unsigned OpNo,
477 raw_ostream &O) {
478 if (OpNo < MI->getNumOperands()) {
479 SPIRV::Decoration e =
480 static_cast<SPIRV::Decoration>(MI->getOperand(OpNo).getImm());
481 O << SPIRV::getDecorationName(e);
482 }
483 }
484
printBuiltIn(const MCInst * MI,unsigned OpNo,raw_ostream & O)485 void SPIRVInstPrinter::printBuiltIn(const MCInst *MI, unsigned OpNo,
486 raw_ostream &O) {
487 if (OpNo < MI->getNumOperands()) {
488 SPIRV::BuiltIn e =
489 static_cast<SPIRV::BuiltIn>(MI->getOperand(OpNo).getImm());
490 O << SPIRV::getBuiltInName(e);
491 }
492 }
493
printSelectionControl(const MCInst * MI,unsigned OpNo,raw_ostream & O)494 void SPIRVInstPrinter::printSelectionControl(const MCInst *MI, unsigned OpNo,
495 raw_ostream &O) {
496 if (OpNo < MI->getNumOperands()) {
497 unsigned e = static_cast<unsigned>(MI->getOperand(OpNo).getImm());
498 O << SPIRV::getSelectionControlName(e);
499 }
500 }
501
printLoopControl(const MCInst * MI,unsigned OpNo,raw_ostream & O)502 void SPIRVInstPrinter::printLoopControl(const MCInst *MI, unsigned OpNo,
503 raw_ostream &O) {
504 if (OpNo < MI->getNumOperands()) {
505 unsigned e = static_cast<unsigned>(MI->getOperand(OpNo).getImm());
506 O << SPIRV::getLoopControlName(e);
507 }
508 }
509
printFunctionControl(const MCInst * MI,unsigned OpNo,raw_ostream & O)510 void SPIRVInstPrinter::printFunctionControl(const MCInst *MI, unsigned OpNo,
511 raw_ostream &O) {
512 if (OpNo < MI->getNumOperands()) {
513 unsigned e = static_cast<unsigned>(MI->getOperand(OpNo).getImm());
514 O << SPIRV::getFunctionControlName(e);
515 }
516 }
517
printMemorySemantics(const MCInst * MI,unsigned OpNo,raw_ostream & O)518 void SPIRVInstPrinter::printMemorySemantics(const MCInst *MI, unsigned OpNo,
519 raw_ostream &O) {
520 if (OpNo < MI->getNumOperands()) {
521 unsigned e = static_cast<unsigned>(MI->getOperand(OpNo).getImm());
522 O << SPIRV::getMemorySemanticsName(e);
523 }
524 }
525
printMemoryOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)526 void SPIRVInstPrinter::printMemoryOperand(const MCInst *MI, unsigned OpNo,
527 raw_ostream &O) {
528 if (OpNo < MI->getNumOperands()) {
529 unsigned e = static_cast<unsigned>(MI->getOperand(OpNo).getImm());
530 O << SPIRV::getMemoryOperandName(e);
531 }
532 }
533
printScope(const MCInst * MI,unsigned OpNo,raw_ostream & O)534 void SPIRVInstPrinter::printScope(const MCInst *MI, unsigned OpNo,
535 raw_ostream &O) {
536 if (OpNo < MI->getNumOperands()) {
537 SPIRV::Scope e = static_cast<SPIRV::Scope>(MI->getOperand(OpNo).getImm());
538 O << SPIRV::getScopeName(e);
539 }
540 }
541
printGroupOperation(const MCInst * MI,unsigned OpNo,raw_ostream & O)542 void SPIRVInstPrinter::printGroupOperation(const MCInst *MI, unsigned OpNo,
543 raw_ostream &O) {
544 if (OpNo < MI->getNumOperands()) {
545 SPIRV::GroupOperation e =
546 static_cast<SPIRV::GroupOperation>(MI->getOperand(OpNo).getImm());
547 O << SPIRV::getGroupOperationName(e);
548 }
549 }
550
printKernelEnqueueFlags(const MCInst * MI,unsigned OpNo,raw_ostream & O)551 void SPIRVInstPrinter::printKernelEnqueueFlags(const MCInst *MI, unsigned OpNo,
552 raw_ostream &O) {
553 if (OpNo < MI->getNumOperands()) {
554 SPIRV::KernelEnqueueFlags e =
555 static_cast<SPIRV::KernelEnqueueFlags>(MI->getOperand(OpNo).getImm());
556 O << SPIRV::getKernelEnqueueFlagsName(e);
557 }
558 }
559
printKernelProfilingInfo(const MCInst * MI,unsigned OpNo,raw_ostream & O)560 void SPIRVInstPrinter::printKernelProfilingInfo(const MCInst *MI, unsigned OpNo,
561 raw_ostream &O) {
562 if (OpNo < MI->getNumOperands()) {
563 SPIRV::KernelProfilingInfo e =
564 static_cast<SPIRV::KernelProfilingInfo>(MI->getOperand(OpNo).getImm());
565 O << SPIRV::getKernelProfilingInfoName(e);
566 }
567 }
568