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 printOpExtInst(MI, OS);
181 } else if (OpCode == SPIRV::UNKNOWN_type) {
182 printUnknownType(MI, OS);
183 } else {
184 // Print any extra operands for variadic instructions.
185 const MCInstrDesc &MCDesc = MII.get(OpCode);
186 if (MCDesc.isVariadic()) {
187 const unsigned NumFixedOps = MCDesc.getNumOperands();
188 const unsigned LastFixedIndex = NumFixedOps - 1;
189 const int FirstVariableIndex = NumFixedOps;
190 if (NumFixedOps > 0 && MCDesc.operands()[LastFixedIndex].OperandType ==
192 // For instructions where a custom type (not reg or immediate) comes as
193 // the last operand before the variable_ops. This is usually a StringImm
194 // operand, but there are a few other cases.
195 switch (OpCode) {
196 case SPIRV::OpTypeImage:
197 OS << ' ';
199 MI, FirstVariableIndex, OS);
200 break;
201 case SPIRV::OpVariable:
202 OS << ' ';
203 printOperand(MI, FirstVariableIndex, OS);
204 break;
205 case SPIRV::OpEntryPoint: {
206 // Print the interface ID operands, skipping the name's string
207 // literal.
208 printRemainingVariableOps(MI, NumFixedOps, OS, false, true);
209 break;
210 }
211 case SPIRV::OpMemberDecorate:
212 printRemainingVariableOps(MI, NumFixedOps, OS);
213 break;
214 case SPIRV::OpExecutionMode:
215 case SPIRV::OpExecutionModeId:
216 case SPIRV::OpLoopMerge:
217 case SPIRV::OpLoopControlINTEL: {
218 // Print any literals after the OPERAND_UNKNOWN argument normally.
219 printRemainingVariableOps(MI, NumFixedOps, OS);
220 break;
221 }
222 default:
223 break; // printStringImm has already been handled.
224 }
225 } else {
226 // For instructions with no fixed ops or a reg/immediate as the final
227 // fixed operand, we can usually print the rest with "printOperand", but
228 // check for a few cases with custom types first.
229 switch (OpCode) {
230 case SPIRV::OpLoad:
231 case SPIRV::OpStore:
232 printMemoryOperand(MI, FirstVariableIndex, OS);
233 break;
234 case SPIRV::OpSwitch:
235 if (MI->getFlags() & SPIRV::INST_PRINTER_WIDTH64) {
236 // In binary format 64-bit types are split into two 32-bit operands,
237 // but in text format combine these into a single 64-bit value as
238 // this is what tools such as spirv-as require.
239 const unsigned NumOps = MI->getNumOperands();
240 for (unsigned OpIdx = NumFixedOps; OpIdx < NumOps;) {
241 if (OpIdx + 1 >= NumOps || !MI->getOperand(OpIdx).isImm() ||
242 !MI->getOperand(OpIdx + 1).isImm()) {
243 llvm_unreachable("Unexpected OpSwitch operands");
244 continue;
245 }
246 OS << ' ';
247 uint64_t LowBits = MI->getOperand(OpIdx).getImm();
248 uint64_t HighBits = MI->getOperand(OpIdx + 1).getImm();
249 uint64_t CombinedValue = (HighBits << 32) | LowBits;
250 OS << formatImm(CombinedValue);
251 OpIdx += 2;
252
253 // Next should be the label
254 if (OpIdx < NumOps) {
255 OS << ' ';
256 printOperand(MI, OpIdx, OS);
257 OpIdx++;
258 }
259 }
260 } else {
261 printRemainingVariableOps(MI, NumFixedOps, OS);
262 }
263 break;
264 case SPIRV::OpImageSampleImplicitLod:
265 case SPIRV::OpImageSampleDrefImplicitLod:
266 case SPIRV::OpImageSampleProjImplicitLod:
267 case SPIRV::OpImageSampleProjDrefImplicitLod:
268 case SPIRV::OpImageFetch:
269 case SPIRV::OpImageGather:
270 case SPIRV::OpImageDrefGather:
271 case SPIRV::OpImageRead:
272 case SPIRV::OpImageWrite:
273 case SPIRV::OpImageSparseSampleImplicitLod:
274 case SPIRV::OpImageSparseSampleDrefImplicitLod:
275 case SPIRV::OpImageSparseSampleProjImplicitLod:
276 case SPIRV::OpImageSparseSampleProjDrefImplicitLod:
277 case SPIRV::OpImageSparseFetch:
278 case SPIRV::OpImageSparseGather:
279 case SPIRV::OpImageSparseDrefGather:
280 case SPIRV::OpImageSparseRead:
281 case SPIRV::OpImageSampleFootprintNV:
282 OS << ' ';
284 MI, FirstVariableIndex, OS);
285 printRemainingVariableOps(MI, NumFixedOps + 1, OS);
286 break;
287 case SPIRV::OpCopyMemory:
288 case SPIRV::OpCopyMemorySized: {
289 const unsigned NumOps = MI->getNumOperands();
290 for (unsigned i = NumFixedOps; i < NumOps;)
291 i = printMemoryOperand(MI, i, OS);
292 break;
293 }
294 case SPIRV::OpConstantI:
295 case SPIRV::OpConstantF:
296 // The last fixed operand along with any variadic operands that follow
297 // are part of the variable value.
298 assert(NumFixedOps > 0 && "Expected at least one fixed operand");
299 printOpConstantVarOps(MI, NumFixedOps - 1, OS);
300 break;
301 case SPIRV::OpCooperativeMatrixMulAddKHR: {
302 const unsigned NumOps = MI->getNumOperands();
303 if (NumFixedOps == NumOps)
304 break;
305
306 OS << ' ';
307 const unsigned MulAddOp = MI->getOperand(FirstVariableIndex).getImm();
308 if (MulAddOp == 0) {
310 OperandCategory::CooperativeMatrixOperandsOperand>(
311 MI, FirstVariableIndex, OS);
312 } else {
313 std::string Buffer;
314 for (unsigned Mask = 0x1;
315 Mask != SPIRV::CooperativeMatrixOperands::
316 MatrixResultBFloat16ComponentsINTEL;
317 Mask <<= 1) {
318 if (MulAddOp & Mask) {
319 if (!Buffer.empty())
320 Buffer += '|';
322 OperandCategory::CooperativeMatrixOperandsOperand, Mask);
323 }
324 }
325 OS << Buffer;
326 }
327 break;
328 }
329 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
330 const unsigned NumOps = MI->getNumOperands();
331 if (NumFixedOps >= NumOps)
332 break;
333 OS << ' ';
334 const unsigned Flags = MI->getOperand(NumOps - 1).getImm();
335 if (Flags == 0) {
337 OperandCategory::MatrixMultiplyAccumulateOperandsOperand>(
338 MI, NumOps - 1, OS);
339 } else {
340 std::string Buffer;
341 for (unsigned Mask = 0x1;
342 Mask <= SPIRV::MatrixMultiplyAccumulateOperands::
343 MatrixBPackedBFloat16INTEL;
344 Mask <<= 1) {
345 if (Flags & Mask) {
346 if (!Buffer.empty())
347 Buffer += '|';
349 OperandCategory::MatrixMultiplyAccumulateOperandsOperand,
350 Mask);
351 }
352 }
353 OS << Buffer;
354 }
355 break;
356 }
357 case SPIRV::OpSDot:
358 case SPIRV::OpUDot:
359 case SPIRV::OpSUDot:
360 case SPIRV::OpSDotAccSat:
361 case SPIRV::OpUDotAccSat:
362 case SPIRV::OpSUDotAccSat: {
363 const unsigned NumOps = MI->getNumOperands();
364 if (NumOps > NumFixedOps) {
365 OS << ' ';
367 MI, NumOps - 1, OS);
368 break;
369 }
370 break;
371 }
372 case SPIRV::OpPredicatedLoadINTEL:
373 case SPIRV::OpPredicatedStoreINTEL: {
374 if (MI->getNumOperands() > NumFixedOps)
375 printMemoryOperand(MI, NumFixedOps, OS);
376 break;
377 }
378 default:
379 printRemainingVariableOps(MI, NumFixedOps, OS);
380 break;
381 }
382 }
383 }
384 }
385
386 printAnnotation(OS, Annot);
387}
388
390 // The fixed operands have already been printed, so just need to decide what
391 // type of ExtInst operands to print based on the instruction set and number.
392 const MCInstrDesc &MCDesc = MII.get(MI->getOpcode());
393 unsigned NumFixedOps = MCDesc.getNumOperands();
394 const auto NumOps = MI->getNumOperands();
395 if (NumOps == NumFixedOps)
396 return;
397
398 O << ' ';
399
400 // TODO: implement special printing for OpenCLExtInst::vstor*.
401 printRemainingVariableOps(MI, NumFixedOps, O, true);
402}
403
405 // The fixed operands have already been printed, so just need to decide what
406 // type of decoration operands to print based on the Decoration type.
407 const MCInstrDesc &MCDesc = MII.get(MI->getOpcode());
408 unsigned NumFixedOps = MCDesc.getNumOperands();
409
410 if (NumFixedOps != MI->getNumOperands()) {
411 auto DecOp = MI->getOperand(NumFixedOps - 1);
412 auto Dec = static_cast<Decoration::Decoration>(DecOp.getImm());
413
414 O << ' ';
415
416 switch (Dec) {
417 case Decoration::BuiltIn:
419 break;
420 case Decoration::UniformId:
421 printOperand(MI, NumFixedOps, O);
422 break;
423 case Decoration::FuncParamAttr:
425 MI, NumFixedOps, O);
426 break;
427 case Decoration::FPRoundingMode:
429 MI, NumFixedOps, O);
430 break;
431 case Decoration::FPFastMathMode:
433 MI, NumFixedOps, O);
434 break;
435 case Decoration::LinkageAttributes:
436 case Decoration::UserSemantic:
437 printStringImm(MI, NumFixedOps, O);
438 break;
439 case Decoration::HostAccessINTEL:
440 printOperand(MI, NumFixedOps, O);
441 if (NumFixedOps + 1 < MI->getNumOperands()) {
442 O << ' ';
443 printStringImm(MI, NumFixedOps + 1, O);
444 }
445 break;
446 default:
447 printRemainingVariableOps(MI, NumFixedOps, O, true);
448 break;
449 }
450 }
451}
452
454 const auto EnumOperand = MI->getOperand(1);
455 assert(EnumOperand.isImm() &&
456 "second operand of UNKNOWN_type must be opcode!");
457
458 const auto Enumerant = EnumOperand.getImm();
459 const auto NumOps = MI->getNumOperands();
460
461 // Print the opcode using the spirv-as unknown opcode syntax
462 O << "OpUnknown(" << Enumerant << ", " << NumOps << ") ";
463
464 // The result ID must be printed after the opcode when using this syntax
465 printOperand(MI, 0, O);
466
467 O << " ";
468
469 const MCInstrDesc &MCDesc = MII.get(MI->getOpcode());
470 unsigned NumFixedOps = MCDesc.getNumOperands();
471 if (NumOps == NumFixedOps)
472 return;
473
474 // Print the rest of the operands
475 printRemainingVariableOps(MI, NumFixedOps, O, true);
476}
477
478void SPIRVInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
479 raw_ostream &O) {
480 if (OpNo < MI->getNumOperands()) {
481 const MCOperand &Op = MI->getOperand(OpNo);
482 if (Op.isReg())
483 O << '%' << (getIDFromRegister(Op.getReg().id()) + 1);
484 else if (Op.isImm()) {
485 int64_t Imm = Op.getImm();
486 // For OpVectorShuffle:
487 // A Component literal may also be FFFFFFFF, which means the corresponding
488 // result component has no source and is undefined.
489 // LLVM representation of poison/undef becomes -1 when lowered to MI.
490 if (MI->getOpcode() == SPIRV::OpVectorShuffle && Imm == -1)
491 O << "0xFFFFFFFF";
492 else
493 O << formatImm(Imm);
494 } else if (Op.isDFPImm())
495 O << formatImm((double)Op.getDFPImm());
496 else if (Op.isExpr())
497 MAI.printExpr(O, *Op.getExpr());
498 else
499 llvm_unreachable("Unexpected operand type");
500 }
501}
502
503void SPIRVInstPrinter::printStringImm(const MCInst *MI, unsigned OpNo,
504 raw_ostream &O) {
505 const unsigned NumOps = MI->getNumOperands();
506 unsigned StrStartIndex = OpNo;
507 while (StrStartIndex < NumOps) {
508 if (MI->getOperand(StrStartIndex).isReg())
509 break;
510
511 std::string Str = getSPIRVStringOperand(*MI, StrStartIndex);
512 if (StrStartIndex != OpNo)
513 O << ' '; // Add a space if we're starting a new string/argument.
514 O << '"';
515 for (char c : Str) {
516 // Escape ", \n characters (might break for complex UTF-8).
517 if (c == '\n') {
518 O.write("\\n", 2);
519 } else {
520 if (c == '"')
521 O.write('\\');
522 O.write(c);
523 }
524 }
525 O << '"';
526
527 unsigned numOpsInString = (Str.size() / 4) + 1;
528 StrStartIndex += numOpsInString;
529
530 // Check for final Op of "OpDecorate %x %stringImm %linkageAttribute".
531 if (MI->getOpcode() == SPIRV::OpDecorate &&
532 MI->getOperand(1).getImm() ==
533 static_cast<unsigned>(Decoration::LinkageAttributes)) {
534 O << ' ';
536 MI, StrStartIndex, O);
537 break;
538 }
539 }
540}
541
542void SPIRVInstPrinter::printExtension(const MCInst *MI, unsigned OpNo,
543 raw_ostream &O) {
544 auto SetReg = MI->getOperand(2).getReg();
545 auto Set = ExtInstSetIDs[SetReg];
546 auto Op = MI->getOperand(OpNo).getImm();
547 O << getExtInstName(Set, Op);
548}
549
550template <OperandCategory::OperandCategory category>
552 raw_ostream &O) {
553 if (OpNo < MI->getNumOperands()) {
554 O << getSymbolicOperandMnemonic(category, MI->getOperand(OpNo).getImm());
555 }
556}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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:258
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
Definition APFloat.cpp:254
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
Definition APInt.cpp:968
LLVM_ABI void print(raw_ostream &OS, bool isSigned) const
Definition APInt.cpp:2342
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:144
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