29#define DEBUG_TYPE "asm-printer"
32#include "SPIRVGenAsmWriter.inc"
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)
53 const unsigned NumVarOps =
MI->getNumOperands() - StartIndex;
55 if (
MI->getOpcode() == SPIRV::OpConstantI && NumVarOps > 2) {
59 unsigned Bitwidth = IntTypeBitwidths.at(IntTypeReg);
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);
71 ActualVal.
print(O,
false);
75 assert((NumVarOps == 1 || NumVarOps == 2) &&
76 "Unsupported number of bits for literal variable");
80 uint64_t
Imm =
MI->getOperand(StartIndex).getImm();
84 Imm |= (
MI->getOperand(StartIndex + 1).
getImm() << 32);
88 if (
MI->getOpcode() == SPIRV::OpConstantF && IsBitwidth16 == 0) {
96 if (
FP.isInfinity() ||
FP.isNaN()) {
100 if (
FP.isInfinity()) {
101 O <<
"0x1p+" << MaxExp;
103 unsigned MantissaBits =
106 unsigned Pad =
alignTo(MantissaBits, 4) - MantissaBits;
107 std::string Hex =
utohexstr(Mantissa << Pad,
true,
108 (MantissaBits + Pad) / 4);
109 while (Hex.size() > 1 && Hex.back() ==
'0')
111 O <<
"0x1." << Hex <<
"p+" << MaxExp;
118 O <<
format(
"%.*g", std::numeric_limits<double>::max_digits10,
119 FP.convertToDouble());
131 if (OpNo >=
MI->getNumOperands())
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,
143 for (uint64_t ParamMask : ParameterizedMasks) {
144 if (!(Mask & ParamMask))
153void SPIRVInstPrinter::recordIntType(
const MCInst *
MI) {
155 unsigned Bitwidth =
MI->getOperand(1).getImm();
156 IntTypeBitwidths[IntTypeReg] = Bitwidth;
159void SPIRVInstPrinter::recordOpExtInstImport(
const MCInst *
MI) {
163 ExtInstSetIDs.insert({
Reg, Set});
169 const unsigned OpCode =
MI->getOpcode();
171 if (OpCode == SPIRV::OpTypeInt) {
175 if (OpCode == SPIRV::OpDecorate || OpCode == SPIRV::OpDecorateId) {
177 }
else if (OpCode == SPIRV::OpExtInstImport) {
178 recordOpExtInstImport(
MI);
179 }
else if (OpCode == SPIRV::OpExtInst ||
180 OpCode == SPIRV::OpExtInstWithForwardRefsKHR) {
182 }
else if (OpCode == SPIRV::UNKNOWN_type) {
189 const unsigned LastFixedIndex = NumFixedOps - 1;
190 const int FirstVariableIndex = NumFixedOps;
191 if (NumFixedOps > 0 && MCDesc.
operands()[LastFixedIndex].OperandType ==
197 case SPIRV::OpTypeImage:
200 MI, FirstVariableIndex, OS);
202 case SPIRV::OpVariable:
206 case SPIRV::OpEntryPoint: {
212 case SPIRV::OpMemberDecorate:
215 case SPIRV::OpExecutionMode:
216 case SPIRV::OpExecutionModeId:
217 case SPIRV::OpLoopMerge:
218 case SPIRV::OpLoopControlINTEL: {
235 case SPIRV::OpSwitch:
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()) {
248 uint64_t LowBits =
MI->getOperand(OpIdx).getImm();
249 uint64_t HighBits =
MI->getOperand(OpIdx + 1).getImm();
250 uint64_t CombinedValue = (HighBits << 32) | LowBits;
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:
285 MI, FirstVariableIndex, OS);
288 case SPIRV::OpCopyMemory:
289 case SPIRV::OpCopyMemorySized: {
290 const unsigned NumOps =
MI->getNumOperands();
291 for (
unsigned i = NumFixedOps; i <
NumOps;)
295 case SPIRV::OpConstantI:
296 case SPIRV::OpConstantF:
299 assert(NumFixedOps > 0 &&
"Expected at least one fixed operand");
302 case SPIRV::OpCooperativeMatrixMulAddKHR: {
303 const unsigned NumOps =
MI->getNumOperands();
304 if (NumFixedOps ==
NumOps)
308 const unsigned MulAddOp =
MI->getOperand(FirstVariableIndex).getImm();
311 OperandCategory::CooperativeMatrixOperandsOperand>(
312 MI, FirstVariableIndex, OS);
315 for (
unsigned Mask = 0x1;
316 Mask != SPIRV::CooperativeMatrixOperands::
317 MatrixResultBFloat16ComponentsINTEL;
319 if (MulAddOp & Mask) {
323 OperandCategory::CooperativeMatrixOperandsOperand, Mask);
330 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
331 const unsigned NumOps =
MI->getNumOperands();
332 if (NumFixedOps >=
NumOps)
335 const unsigned Flags =
MI->getOperand(
NumOps - 1).getImm();
338 OperandCategory::MatrixMultiplyAccumulateOperandsOperand>(
342 for (
unsigned Mask = 0x1;
343 Mask <= SPIRV::MatrixMultiplyAccumulateOperands::
344 MatrixBPackedBFloat16INTEL;
350 OperandCategory::MatrixMultiplyAccumulateOperandsOperand,
361 case SPIRV::OpSDotAccSat:
362 case SPIRV::OpUDotAccSat:
363 case SPIRV::OpSUDotAccSat: {
364 const unsigned NumOps =
MI->getNumOperands();
365 if (
NumOps > NumFixedOps) {
373 case SPIRV::OpPredicatedLoadINTEL:
374 case SPIRV::OpPredicatedStoreINTEL: {
375 if (
MI->getNumOperands() > NumFixedOps)
395 const auto NumOps =
MI->getNumOperands();
396 if (
NumOps == NumFixedOps)
411 if (NumFixedOps !=
MI->getNumOperands()) {
412 auto DecOp =
MI->getOperand(NumFixedOps - 1);
413 auto Dec =
static_cast<Decoration::Decoration
>(DecOp.getImm());
418 case Decoration::BuiltIn:
421 case Decoration::UniformId:
424 case Decoration::FuncParamAttr:
428 case Decoration::FPRoundingMode:
432 case Decoration::FPFastMathMode:
436 case Decoration::LinkageAttributes:
437 case Decoration::UserSemantic:
440 case Decoration::HostAccessINTEL:
442 if (NumFixedOps + 1 <
MI->getNumOperands()) {
455 const auto EnumOperand =
MI->getOperand(1);
456 assert(EnumOperand.isImm() &&
457 "second operand of UNKNOWN_type must be opcode!");
459 const auto Enumerant = EnumOperand.getImm();
460 const auto NumOps =
MI->getNumOperands();
463 O <<
"OpUnknown(" << Enumerant <<
", " <<
NumOps <<
") ";
472 if (
NumOps == NumFixedOps)
481 if (OpNo < MI->getNumOperands()) {
485 else if (
Op.isImm()) {
486 int64_t
Imm =
Op.getImm();
491 if (
MI->getOpcode() == SPIRV::OpVectorShuffle &&
Imm == -1)
495 }
else if (
Op.isDFPImm())
497 else if (
Op.isExpr())
498 MAI.printExpr(O, *
Op.getExpr());
506 const unsigned NumOps =
MI->getNumOperands();
507 unsigned StrStartIndex = OpNo;
508 while (StrStartIndex <
NumOps) {
509 if (
MI->getOperand(StrStartIndex).isReg())
513 if (StrStartIndex != OpNo)
528 unsigned numOpsInString = (Str.size() / 4) + 1;
529 StrStartIndex += numOpsInString;
532 if (
MI->getOpcode() == SPIRV::OpDecorate &&
533 MI->getOperand(1).getImm() ==
534 static_cast<unsigned>(Decoration::LinkageAttributes)) {
537 MI, StrStartIndex, O);
545 auto SetReg =
MI->getOperand(2).getReg();
546 auto Set = ExtInstSetIDs[SetReg];
547 auto Op =
MI->getOperand(OpNo).getImm();
551template <OperandCategory::OperandCategory category>
554 if (OpNo < MI->getNumOperands()) {
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...
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
static LLVM_ABI ExponentType semanticsMaxExponent(const fltSemantics &)
static LLVM_ABI unsigned int semanticsPrecision(const fltSemantics &)
Class for arbitrary precision integers.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
LLVM_ABI void print(raw_ostream &OS, bool isSigned) const
void printAnnotation(raw_ostream &OS, StringRef Annot)
Utility function for printing annotations.
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.
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.
Wrapper class representing physical registers. Should be passed by value.
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.
This class implements an extremely fast bulk output stream that can only output to a stream.
#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.
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.
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.