27#define DEBUG_TYPE "asm-printer"
30#include "SPIRVGenAsmWriter.inc"
36 bool SkipImmediates) {
37 const unsigned NumOps =
MI->getNumOperands();
38 for (
unsigned i = StartIndex; i <
NumOps; ++i) {
39 if (!SkipImmediates || !
MI->getOperand(i).isImm()) {
40 if (!SkipFirstSpace || i != StartIndex)
51 const unsigned NumVarOps =
MI->getNumOperands() - StartIndex;
53 assert((NumVarOps == 1 || NumVarOps == 2) &&
54 "Unsupported number of bits for literal variable");
58 uint64_t Imm =
MI->getOperand(StartIndex).getImm();
62 Imm |= (
MI->getOperand(StartIndex + 1).
getImm() << 32);
66 if (
MI->getOpcode() == SPIRV::OpConstantF && IsBitwidth16 == 0) {
73 if (
FP.isInfinity()) {
86 O <<
format(
"%.*g", std::numeric_limits<double>::max_digits10,
87 FP.convertToDouble());
96void SPIRVInstPrinter::recordOpExtInstImport(
const MCInst *
MI) {
100 ExtInstSetIDs.
insert({Reg, Set});
106 const unsigned OpCode =
MI->getOpcode();
109 if (OpCode == SPIRV::OpDecorate) {
111 }
else if (OpCode == SPIRV::OpExtInstImport) {
112 recordOpExtInstImport(
MI);
113 }
else if (OpCode == SPIRV::OpExtInst) {
115 }
else if (OpCode == SPIRV::UNKNOWN_type) {
122 const unsigned LastFixedIndex = NumFixedOps - 1;
123 const int FirstVariableIndex = NumFixedOps;
124 if (NumFixedOps > 0 && MCDesc.
operands()[LastFixedIndex].OperandType ==
130 case SPIRV::OpTypeImage:
133 MI, FirstVariableIndex, OS);
135 case SPIRV::OpVariable:
139 case SPIRV::OpEntryPoint: {
145 case SPIRV::OpMemberDecorate:
148 case SPIRV::OpExecutionMode:
149 case SPIRV::OpExecutionModeId:
150 case SPIRV::OpLoopMerge: {
167 MI, FirstVariableIndex, OS);
170 case SPIRV::OpSwitch:
175 const unsigned NumOps =
MI->getNumOperands();
178 !
MI->getOperand(
OpIdx + 1).isImm()) {
185 uint64_t CombinedValue = (HighBits << 32) | LowBits;
200 case SPIRV::OpImageSampleImplicitLod:
201 case SPIRV::OpImageSampleDrefImplicitLod:
202 case SPIRV::OpImageSampleProjImplicitLod:
203 case SPIRV::OpImageSampleProjDrefImplicitLod:
204 case SPIRV::OpImageFetch:
205 case SPIRV::OpImageGather:
206 case SPIRV::OpImageDrefGather:
207 case SPIRV::OpImageRead:
208 case SPIRV::OpImageWrite:
209 case SPIRV::OpImageSparseSampleImplicitLod:
210 case SPIRV::OpImageSparseSampleDrefImplicitLod:
211 case SPIRV::OpImageSparseSampleProjImplicitLod:
212 case SPIRV::OpImageSparseSampleProjDrefImplicitLod:
213 case SPIRV::OpImageSparseFetch:
214 case SPIRV::OpImageSparseGather:
215 case SPIRV::OpImageSparseDrefGather:
216 case SPIRV::OpImageSparseRead:
217 case SPIRV::OpImageSampleFootprintNV:
220 MI, FirstVariableIndex, OS);
223 case SPIRV::OpCopyMemory:
224 case SPIRV::OpCopyMemorySized: {
225 const unsigned NumOps =
MI->getNumOperands();
226 for (
unsigned i = NumFixedOps; i <
NumOps; ++i) {
230 if (
MI->getOperand(i).getImm() & MemoryOperand::Aligned) {
239 case SPIRV::OpConstantI:
240 case SPIRV::OpConstantF:
243 assert(NumFixedOps > 0 &&
"Expected at least one fixed operand");
246 case SPIRV::OpCooperativeMatrixMulAddKHR: {
247 const unsigned NumOps =
MI->getNumOperands();
248 if (NumFixedOps ==
NumOps)
252 const unsigned MulAddOp =
MI->getOperand(FirstVariableIndex).getImm();
255 OperandCategory::CooperativeMatrixOperandsOperand>(
256 MI, FirstVariableIndex, OS);
259 for (
unsigned Mask = 0x1;
260 Mask != SPIRV::CooperativeMatrixOperands::
261 MatrixResultBFloat16ComponentsINTEL;
263 if (MulAddOp & Mask) {
267 OperandCategory::CooperativeMatrixOperandsOperand, Mask);
274 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
275 const unsigned NumOps =
MI->getNumOperands();
276 if (NumFixedOps >=
NumOps)
279 const unsigned Flags =
MI->getOperand(
NumOps - 1).getImm();
282 OperandCategory::MatrixMultiplyAccumulateOperandsOperand>(
286 for (
unsigned Mask = 0x1;
287 Mask <= SPIRV::MatrixMultiplyAccumulateOperands::
288 MatrixBPackedBFloat16INTEL;
294 OperandCategory::MatrixMultiplyAccumulateOperandsOperand,
305 case SPIRV::OpSDotAccSat:
306 case SPIRV::OpUDotAccSat:
307 case SPIRV::OpSUDotAccSat: {
308 const unsigned NumOps =
MI->getNumOperands();
309 if (
NumOps > NumFixedOps) {
317 case SPIRV::OpPredicatedLoadINTEL:
318 case SPIRV::OpPredicatedStoreINTEL: {
319 const unsigned NumOps =
MI->getNumOperands();
320 if (
NumOps > NumFixedOps) {
344 const auto NumOps =
MI->getNumOperands();
345 if (
NumOps == NumFixedOps)
360 if (NumFixedOps !=
MI->getNumOperands()) {
361 auto DecOp =
MI->getOperand(NumFixedOps - 1);
362 auto Dec =
static_cast<Decoration::Decoration
>(DecOp.getImm());
367 case Decoration::BuiltIn:
370 case Decoration::UniformId:
373 case Decoration::FuncParamAttr:
377 case Decoration::FPRoundingMode:
381 case Decoration::FPFastMathMode:
385 case Decoration::LinkageAttributes:
386 case Decoration::UserSemantic:
389 case Decoration::HostAccessINTEL:
391 if (NumFixedOps + 1 <
MI->getNumOperands()) {
404 const auto EnumOperand =
MI->getOperand(1);
405 assert(EnumOperand.isImm() &&
406 "second operand of UNKNOWN_type must be opcode!");
408 const auto Enumerant = EnumOperand.getImm();
409 const auto NumOps =
MI->getNumOperands();
412 O <<
"OpUnknown(" << Enumerant <<
", " <<
NumOps <<
") ";
421 if (
NumOps == NumFixedOps)
430 if (OpNo < MI->getNumOperands()) {
434 else if (
Op.isImm()) {
435 int64_t Imm =
Op.getImm();
440 if (
MI->getOpcode() == SPIRV::OpVectorShuffle && Imm == -1)
444 }
else if (
Op.isDFPImm())
446 else if (
Op.isExpr())
447 MAI.printExpr(O, *
Op.getExpr());
455 const unsigned NumOps =
MI->getNumOperands();
456 unsigned StrStartIndex = OpNo;
457 while (StrStartIndex <
NumOps) {
458 if (
MI->getOperand(StrStartIndex).isReg())
462 if (StrStartIndex != OpNo)
477 unsigned numOpsInString = (Str.size() / 4) + 1;
478 StrStartIndex += numOpsInString;
481 if (
MI->getOpcode() == SPIRV::OpDecorate &&
482 MI->getOperand(1).getImm() ==
483 static_cast<unsigned>(Decoration::LinkageAttributes)) {
486 MI, StrStartIndex, O);
494 auto SetReg =
MI->getOperand(2).getReg();
495 auto Set = ExtInstSetIDs[SetReg];
496 auto Op =
MI->getOperand(OpNo).getImm();
500template <OperandCategory::OperandCategory category>
503 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
MachineInstr unsigned OpIdx
Class for arbitrary precision integers.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
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)
StringRef - 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)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
std::string getSPIRVStringOperand(const InstType &MI, unsigned StartIndex)
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