LLVM 24.0.0git
SPIRVInstPrinter.cpp
Go to the documentation of this file.
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/ADT/APFloat.h"
18#include "llvm/MC/MCAsmInfo.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
21#include "llvm/MC/MCInstrInfo.h"
22#include "llvm/MC/MCSymbol.h"
25
26using namespace llvm;
27using namespace llvm::SPIRV;
28
29#define DEBUG_TYPE "asm-printer"
30
31// Include the auto-generated portion of the assembly writer.
32#include "SPIRVGenAsmWriter.inc"
33
35 unsigned StartIndex,
36 raw_ostream &O,
37 bool SkipFirstSpace,
38 bool SkipImmediates) {
39 const unsigned NumOps = MI->getNumOperands();
40 for (unsigned i = StartIndex; i < NumOps; ++i) {
41 if (!SkipImmediates || !MI->getOperand(i).isImm()) {
42 if (!SkipFirstSpace || i != StartIndex)
43 O << ' ';
44 printOperand(MI, i, O);
45 }
46 }
47}
48
50 unsigned StartIndex,
51 raw_ostream &O) {
52 unsigned IsBitwidth16 = MI->getFlags() & SPIRV::INST_PRINTER_WIDTH16;
53 const unsigned NumVarOps = MI->getNumOperands() - StartIndex;
54
55 if (MI->getOpcode() == SPIRV::OpConstantI && NumVarOps > 2) {
56 // Look up the bitwidth of this int type register from
57 // IntTypeBitwidths map.
58 MCRegister IntTypeReg = MI->getOperand(1).getReg();
59 unsigned Bitwidth = IntTypeBitwidths.at(IntTypeReg);
60
61 // SPV_ALTERA_arbitrary_precision_integers allows for integer widths greater
62 // than 64, which will be encoded via multiple operands.
63 const unsigned TotalBits = NumVarOps * 32;
64 APInt Val(TotalBits, 0);
65 for (unsigned i = 0; i < NumVarOps; ++i) {
66 uint64_t Word = MI->getOperand(StartIndex + i).getImm();
67 Val |= APInt(TotalBits, Word) << (i * 32);
68 }
69 APInt ActualVal = Val.trunc(Bitwidth);
70 O << ' ';
71 ActualVal.print(O, /*isSigned=*/false);
72 return;
73 }
74
75 assert((NumVarOps == 1 || NumVarOps == 2) &&
76 "Unsupported number of bits for literal variable");
77
78 O << ' ';
79
80 uint64_t Imm = MI->getOperand(StartIndex).getImm();
81
82 // Handle 64 bit literals.
83 if (NumVarOps == 2) {
84 Imm |= (MI->getOperand(StartIndex + 1).getImm() << 32);
85 }
86
87 // Format and print float values.
88 if (MI->getOpcode() == SPIRV::OpConstantF && IsBitwidth16 == 0) {
89 APFloat FP = NumVarOps == 1 ? APFloat(APInt(32, Imm).bitsToFloat())
90 : APFloat(APInt(64, Imm).bitsToDouble());
91
92 // Print infinity and NaN as hex floats. The exponent depends on the
93 // actual width of FP (f32 vs f64), not a fixed constant.
94 // TODO: Make sure subnormal numbers are handled correctly as they may also
95 // require hex float notation.
96 if (FP.isInfinity() || FP.isNaN()) {
97 unsigned MaxExp = APFloat::semanticsMaxExponent(FP.getSemantics()) + 1;
98 if (FP.isNegative())
99 O << '-';
100 if (FP.isInfinity()) {
101 O << "0x1p+" << MaxExp;
102 } else {
103 unsigned MantissaBits =
104 APFloat::semanticsPrecision(FP.getSemantics()) - 1;
105 uint64_t Mantissa = Imm & (maskTrailingOnes<uint64_t>(MantissaBits));
106 unsigned Pad = alignTo(MantissaBits, 4) - MantissaBits;
107 std::string Hex = utohexstr(Mantissa << Pad, /*LowerCase=*/true,
108 (MantissaBits + Pad) / 4);
109 while (Hex.size() > 1 && Hex.back() == '0')
110 Hex.pop_back();
111 O << "0x1." << Hex << "p+" << MaxExp;
112 }
113 return;
114 }
115
116 // Format val as a decimal floating point or scientific notation (whichever
117 // is shorter), with enough digits of precision to produce the exact value.
118 O << format("%.*g", std::numeric_limits<double>::max_digits10,
119 FP.convertToDouble());
120
121 return;
122 }
123
124 // Print integer values directly.
125 O << Imm;
126}
127
128unsigned SPIRVInstPrinter::printMemoryOperand(const MCInst *MI, unsigned OpNo,
129 raw_ostream &O) {
130 O << ' ';
131 if (OpNo >= MI->getNumOperands())
132 return OpNo;
133 const uint64_t Mask = MI->getOperand(OpNo).getImm();
135 unsigned NextOp = OpNo + 1;
136 static constexpr uint64_t ParameterizedMasks[] = {
137 SPIRV::MemoryOperand::Aligned,
138 SPIRV::MemoryOperand::MakePointerAvailableKHR,
139 SPIRV::MemoryOperand::MakePointerVisibleKHR,
140 SPIRV::MemoryOperand::AliasScopeINTELMask,
141 SPIRV::MemoryOperand::NoAliasINTELMask,
142 };
143 for (uint64_t ParamMask : ParameterizedMasks) {
144 if (!(Mask & ParamMask))
145 continue;
146 O << ' ';
147 printOperand(MI, NextOp, O);
148 ++NextOp;
149 }
150 return NextOp;
151}
152
153void SPIRVInstPrinter::recordIntType(const MCInst *MI) {
154 MCRegister IntTypeReg = MI->getOperand(0).getReg();
155 unsigned Bitwidth = MI->getOperand(1).getImm();
156 IntTypeBitwidths[IntTypeReg] = Bitwidth;
157}
158
159void SPIRVInstPrinter::recordOpExtInstImport(const MCInst *MI) {
160 MCRegister Reg = MI->getOperand(0).getReg();
161 auto Name = getSPIRVStringOperand(*MI, 1);
162 auto Set = getExtInstSetFromString(std::move(Name));
163 ExtInstSetIDs.insert({Reg, Set});
164}
165
167 StringRef Annot, const MCSubtargetInfo &STI,
168 raw_ostream &OS) {
169 const unsigned OpCode = MI->getOpcode();
171 if (OpCode == SPIRV::OpTypeInt) {
172 recordIntType(MI);
173 }
174
175 if (OpCode == SPIRV::OpDecorate || OpCode == SPIRV::OpDecorateId) {
176 printOpDecorate(MI, OS);
177 } else if (OpCode == SPIRV::OpExtInstImport) {
178 recordOpExtInstImport(MI);
179 } else if (OpCode == SPIRV::OpExtInst ||
180 OpCode == SPIRV::OpExtInstWithForwardRefsKHR) {
181 printOpExtInst(MI, OS);
182 } else if (OpCode == SPIRV::UNKNOWN_type) {
183 printUnknownType(MI, OS);
184 } else {
185 // Print any extra operands for variadic instructions.
186 const MCInstrDesc &MCDesc = MII.get(OpCode);
187 if (MCDesc.isVariadic()) {
188 const unsigned NumFixedOps = MCDesc.getNumOperands();
189 const unsigned LastFixedIndex = NumFixedOps - 1;
190 const int FirstVariableIndex = NumFixedOps;
191 if (NumFixedOps > 0 && MCDesc.operands()[LastFixedIndex].OperandType ==
193 // For instructions where a custom type (not reg or immediate) comes as
194 // the last operand before the variable_ops. This is usually a StringImm
195 // operand, but there are a few other cases.
196 switch (OpCode) {
197 case SPIRV::OpTypeImage:
198 OS << ' ';
200 MI, FirstVariableIndex, OS);
201 break;
202 case SPIRV::OpVariable:
203 OS << ' ';
204 printOperand(MI, FirstVariableIndex, OS);
205 break;
206 case SPIRV::OpEntryPoint: {
207 // Print the interface ID operands, skipping the name's string
208 // literal.
209 printRemainingVariableOps(MI, NumFixedOps, OS, false, true);
210 break;
211 }
212 case SPIRV::OpMemberDecorate:
213 printRemainingVariableOps(MI, NumFixedOps, OS);
214 break;
215 case SPIRV::OpExecutionMode:
216 case SPIRV::OpExecutionModeId:
217 case SPIRV::OpLoopMerge:
218 case SPIRV::OpLoopControlINTEL: {
219 // Print any literals after the OPERAND_UNKNOWN argument normally.
220 printRemainingVariableOps(MI, NumFixedOps, OS);
221 break;
222 }
223 default:
224 break; // printStringImm has already been handled.
225 }
226 } else {
227 // For instructions with no fixed ops or a reg/immediate as the final
228 // fixed operand, we can usually print the rest with "printOperand", but
229 // check for a few cases with custom types first.
230 switch (OpCode) {
231 case SPIRV::OpLoad:
232 case SPIRV::OpStore:
233 printMemoryOperand(MI, FirstVariableIndex, OS);
234 break;
235 case SPIRV::OpSwitch:
236 if (MI->getFlags() & SPIRV::INST_PRINTER_WIDTH64) {
237 // In binary format 64-bit types are split into two 32-bit operands,
238 // but in text format combine these into a single 64-bit value as
239 // this is what tools such as spirv-as require.
240 const unsigned NumOps = MI->getNumOperands();
241 for (unsigned OpIdx = NumFixedOps; OpIdx < NumOps;) {
242 if (OpIdx + 1 >= NumOps || !MI->getOperand(OpIdx).isImm() ||
243 !MI->getOperand(OpIdx + 1).isImm()) {
244 llvm_unreachable("Unexpected OpSwitch operands");
245 continue;
246 }
247 OS << ' ';
248 uint64_t LowBits = MI->getOperand(OpIdx).getImm();
249 uint64_t HighBits = MI->getOperand(OpIdx + 1).getImm();
250 uint64_t CombinedValue = (HighBits << 32) | LowBits;
251 OS << formatImm(CombinedValue);
252 OpIdx += 2;
253
254 // Next should be the label
255 if (OpIdx < NumOps) {
256 OS << ' ';
257 printOperand(MI, OpIdx, OS);
258 OpIdx++;
259 }
260 }
261 } else {
262 printRemainingVariableOps(MI, NumFixedOps, OS);
263 }
264 break;
265 case SPIRV::OpImageSampleImplicitLod:
266 case SPIRV::OpImageSampleDrefImplicitLod:
267 case SPIRV::OpImageSampleProjImplicitLod:
268 case SPIRV::OpImageSampleProjDrefImplicitLod:
269 case SPIRV::OpImageFetch:
270 case SPIRV::OpImageGather:
271 case SPIRV::OpImageDrefGather:
272 case SPIRV::OpImageRead:
273 case SPIRV::OpImageWrite:
274 case SPIRV::OpImageSparseSampleImplicitLod:
275 case SPIRV::OpImageSparseSampleDrefImplicitLod:
276 case SPIRV::OpImageSparseSampleProjImplicitLod:
277 case SPIRV::OpImageSparseSampleProjDrefImplicitLod:
278 case SPIRV::OpImageSparseFetch:
279 case SPIRV::OpImageSparseGather:
280 case SPIRV::OpImageSparseDrefGather:
281 case SPIRV::OpImageSparseRead:
282 case SPIRV::OpImageSampleFootprintNV:
283 OS << ' ';
285 MI, FirstVariableIndex, OS);
286 printRemainingVariableOps(MI, NumFixedOps + 1, OS);
287 break;
288 case SPIRV::OpCopyMemory:
289 case SPIRV::OpCopyMemorySized: {
290 const unsigned NumOps = MI->getNumOperands();
291 for (unsigned i = NumFixedOps; i < NumOps;)
292 i = printMemoryOperand(MI, i, OS);
293 break;
294 }
295 case SPIRV::OpConstantI:
296 case SPIRV::OpConstantF:
297 // The last fixed operand along with any variadic operands that follow
298 // are part of the variable value.
299 assert(NumFixedOps > 0 && "Expected at least one fixed operand");
300 printOpConstantVarOps(MI, NumFixedOps - 1, OS);
301 break;
302 case SPIRV::OpCooperativeMatrixMulAddKHR: {
303 const unsigned NumOps = MI->getNumOperands();
304 if (NumFixedOps == NumOps)
305 break;
306
307 OS << ' ';
308 const unsigned MulAddOp = MI->getOperand(FirstVariableIndex).getImm();
309 if (MulAddOp == 0) {
311 OperandCategory::CooperativeMatrixOperandsOperand>(
312 MI, FirstVariableIndex, OS);
313 } else {
314 std::string Buffer;
315 for (unsigned Mask = 0x1;
316 Mask != SPIRV::CooperativeMatrixOperands::
317 MatrixResultBFloat16ComponentsINTEL;
318 Mask <<= 1) {
319 if (MulAddOp & Mask) {
320 if (!Buffer.empty())
321 Buffer += '|';
323 OperandCategory::CooperativeMatrixOperandsOperand, Mask);
324 }
325 }
326 OS << Buffer;
327 }
328 break;
329 }
330 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
331 const unsigned NumOps = MI->getNumOperands();
332 if (NumFixedOps >= NumOps)
333 break;
334 OS << ' ';
335 const unsigned Flags = MI->getOperand(NumOps - 1).getImm();
336 if (Flags == 0) {
338 OperandCategory::MatrixMultiplyAccumulateOperandsOperand>(
339 MI, NumOps - 1, OS);
340 } else {
341 std::string Buffer;
342 for (unsigned Mask = 0x1;
343 Mask <= SPIRV::MatrixMultiplyAccumulateOperands::
344 MatrixBPackedBFloat16INTEL;
345 Mask <<= 1) {
346 if (Flags & Mask) {
347 if (!Buffer.empty())
348 Buffer += '|';
350 OperandCategory::MatrixMultiplyAccumulateOperandsOperand,
351 Mask);
352 }
353 }
354 OS << Buffer;
355 }
356 break;
357 }
358 case SPIRV::OpSDot:
359 case SPIRV::OpUDot:
360 case SPIRV::OpSUDot:
361 case SPIRV::OpSDotAccSat:
362 case SPIRV::OpUDotAccSat:
363 case SPIRV::OpSUDotAccSat: {
364 const unsigned NumOps = MI->getNumOperands();
365 if (NumOps > NumFixedOps) {
366 OS << ' ';
368 MI, NumOps - 1, OS);
369 break;
370 }
371 break;
372 }
373 case SPIRV::OpPredicatedLoadINTEL:
374 case SPIRV::OpPredicatedStoreINTEL: {
375 if (MI->getNumOperands() > NumFixedOps)
376 printMemoryOperand(MI, NumFixedOps, OS);
377 break;
378 }
379 default:
380 printRemainingVariableOps(MI, NumFixedOps, OS);
381 break;
382 }
383 }
384 }
385 }
386
387 printAnnotation(OS, Annot);
388}
389
391 // The fixed operands have already been printed, so just need to decide what
392 // type of ExtInst operands to print based on the instruction set and number.
393 const MCInstrDesc &MCDesc = MII.get(MI->getOpcode());
394 unsigned NumFixedOps = MCDesc.getNumOperands();
395 const auto NumOps = MI->getNumOperands();
396 if (NumOps == NumFixedOps)
397 return;
398
399 O << ' ';
400
401 // TODO: implement special printing for OpenCLExtInst::vstor*.
402 printRemainingVariableOps(MI, NumFixedOps, O, true);
403}
404
406 // The fixed operands have already been printed, so just need to decide what
407 // type of decoration operands to print based on the Decoration type.
408 const MCInstrDesc &MCDesc = MII.get(MI->getOpcode());
409 unsigned NumFixedOps = MCDesc.getNumOperands();
410
411 if (NumFixedOps != MI->getNumOperands()) {
412 auto DecOp = MI->getOperand(NumFixedOps - 1);
413 auto Dec = static_cast<Decoration::Decoration>(DecOp.getImm());
414
415 O << ' ';
416
417 switch (Dec) {
418 case Decoration::BuiltIn:
420 break;
421 case Decoration::UniformId:
422 printOperand(MI, NumFixedOps, O);
423 break;
424 case Decoration::FuncParamAttr:
426 MI, NumFixedOps, O);
427 break;
428 case Decoration::FPRoundingMode:
430 MI, NumFixedOps, O);
431 break;
432 case Decoration::FPFastMathMode:
434 MI, NumFixedOps, O);
435 break;
436 case Decoration::LinkageAttributes:
437 case Decoration::UserSemantic:
438 printStringImm(MI, NumFixedOps, O);
439 break;
440 case Decoration::HostAccessINTEL:
441 printOperand(MI, NumFixedOps, O);
442 if (NumFixedOps + 1 < MI->getNumOperands()) {
443 O << ' ';
444 printStringImm(MI, NumFixedOps + 1, O);
445 }
446 break;
447 default:
448 printRemainingVariableOps(MI, NumFixedOps, O, true);
449 break;
450 }
451 }
452}
453
455 const auto EnumOperand = MI->getOperand(1);
456 assert(EnumOperand.isImm() &&
457 "second operand of UNKNOWN_type must be opcode!");
458
459 const auto Enumerant = EnumOperand.getImm();
460 const auto NumOps = MI->getNumOperands();
461
462 // Print the opcode using the spirv-as unknown opcode syntax
463 O << "OpUnknown(" << Enumerant << ", " << NumOps << ") ";
464
465 // The result ID must be printed after the opcode when using this syntax
466 printOperand(MI, 0, O);
467
468 O << " ";
469
470 const MCInstrDesc &MCDesc = MII.get(MI->getOpcode());
471 unsigned NumFixedOps = MCDesc.getNumOperands();
472 if (NumOps == NumFixedOps)
473 return;
474
475 // Print the rest of the operands
476 printRemainingVariableOps(MI, NumFixedOps, O, true);
477}
478
479void SPIRVInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
480 raw_ostream &O) {
481 if (OpNo < MI->getNumOperands()) {
482 const MCOperand &Op = MI->getOperand(OpNo);
483 if (Op.isReg())
484 O << '%' << (getIDFromRegister(Op.getReg().id()) + 1);
485 else if (Op.isImm()) {
486 int64_t Imm = Op.getImm();
487 // For OpVectorShuffle:
488 // A Component literal may also be FFFFFFFF, which means the corresponding
489 // result component has no source and is undefined.
490 // LLVM representation of poison/undef becomes -1 when lowered to MI.
491 if (MI->getOpcode() == SPIRV::OpVectorShuffle && Imm == -1)
492 O << "0xFFFFFFFF";
493 else
494 O << formatImm(Imm);
495 } else if (Op.isDFPImm())
496 O << formatImm((double)Op.getDFPImm());
497 else if (Op.isExpr())
498 MAI.printExpr(O, *Op.getExpr());
499 else
500 llvm_unreachable("Unexpected operand type");
501 }
502}
503
504void SPIRVInstPrinter::printStringImm(const MCInst *MI, unsigned OpNo,
505 raw_ostream &O) {
506 const unsigned NumOps = MI->getNumOperands();
507 unsigned StrStartIndex = OpNo;
508 while (StrStartIndex < NumOps) {
509 if (MI->getOperand(StrStartIndex).isReg())
510 break;
511
512 std::string Str = getSPIRVStringOperand(*MI, StrStartIndex);
513 if (StrStartIndex != OpNo)
514 O << ' '; // Add a space if we're starting a new string/argument.
515 O << '"';
516 for (char c : Str) {
517 // Escape ", \n characters (might break for complex UTF-8).
518 if (c == '\n') {
519 O.write("\\n", 2);
520 } else {
521 if (c == '"')
522 O.write('\\');
523 O.write(c);
524 }
525 }
526 O << '"';
527
528 unsigned numOpsInString = (Str.size() / 4) + 1;
529 StrStartIndex += numOpsInString;
530
531 // Check for final Op of "OpDecorate %x %stringImm %linkageAttribute".
532 if (MI->getOpcode() == SPIRV::OpDecorate &&
533 MI->getOperand(1).getImm() ==
534 static_cast<unsigned>(Decoration::LinkageAttributes)) {
535 O << ' ';
537 MI, StrStartIndex, O);
538 break;
539 }
540 }
541}
542
543void SPIRVInstPrinter::printExtension(const MCInst *MI, unsigned OpNo,
544 raw_ostream &O) {
545 auto SetReg = MI->getOperand(2).getReg();
546 auto Set = ExtInstSetIDs[SetReg];
547 auto Op = MI->getOperand(OpNo).getImm();
548 O << getExtInstName(Set, Op);
549}
550
551template <OperandCategory::OperandCategory category>
553 raw_ostream &O) {
554 if (OpNo < MI->getNumOperands()) {
555 O << getSymbolicOperandMnemonic(category, MI->getOperand(OpNo).getImm());
556 }
557}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned Imm
This file declares a class to represent arbitrary precision floating point values and provide a varie...
IRTranslator LLVM IR MI
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
Register Reg
This file contains some functions that are useful when dealing with strings.
static LLVM_ABI ExponentType semanticsMaxExponent(const fltSemantics &)
Definition APFloat.cpp:333
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
Definition APFloat.cpp:329
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
Definition APInt.cpp:970
LLVM_ABI void print(raw_ostream &OS, bool isSigned) const
Definition APInt.cpp:2345
const MCInstrInfo & MII
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
const MCAsmInfo & MAI
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:188
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
bool isVariadic() const
Return true if this instruction can have a variable number of operands.
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
Generic base class for all target subtargets.
void printExtension(const MCInst *MI, unsigned OpNo, raw_ostream &O)
void printStringImm(const MCInst *MI, unsigned OpNo, raw_ostream &O)
void printInstruction(const MCInst *MI, uint64_t Address, raw_ostream &O)
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 printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
void printOpExtInst(const MCInst *MI, raw_ostream &O)
void printOpConstantVarOps(const MCInst *MI, unsigned StartIndex, raw_ostream &O)
void printSymbolicOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
void printRemainingVariableOps(const MCInst *MI, unsigned StartIndex, raw_ostream &O, bool SkipFirstSpace=false, bool SkipImmediates=false)
void printOpDecorate(const MCInst *MI, raw_ostream &O)
void printUnknownType(const MCInst *MI, raw_ostream &O)
unsigned printMemoryOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getIDFromRegister(unsigned Reg)
This is an optimization pass for GlobalISel generic memory operations.
std::string getExtInstName(SPIRV::InstructionSet::InstructionSet Set, uint32_t InstructionNumber)
std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
std::string getSPIRVStringOperand(const InstType &MI, unsigned StartIndex)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:149
SPIRV::InstructionSet::InstructionSet getExtInstSetFromString(std::string SetName)
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:102
std::string getSymbolicOperandMnemonic(SPIRV::OperandCategory::OperandCategory Category, int32_t Value)
DWARFExpression::Operation Op
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
Definition MathExtras.h:78