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 if (
MI->getOpcode() == SPIRV::OpConstantI && NumVarOps > 2) {
56 for (
unsigned I = StartIndex;
I !=
MI->getNumOperands(); ++
I)
57 O <<
' ' <<
MI->getOperand(
I).getImm();
61 assert((NumVarOps == 1 || NumVarOps == 2) &&
62 "Unsupported number of bits for literal variable");
66 uint64_t Imm =
MI->getOperand(StartIndex).getImm();
70 Imm |= (
MI->getOperand(StartIndex + 1).
getImm() << 32);
74 if (
MI->getOpcode() == SPIRV::OpConstantF && IsBitwidth16 == 0) {
81 if (
FP.isInfinity()) {
94 O <<
format(
"%.*g", std::numeric_limits<double>::max_digits10,
95 FP.convertToDouble());
104void SPIRVInstPrinter::recordOpExtInstImport(
const MCInst *
MI) {
108 ExtInstSetIDs.insert({Reg, Set});
114 const unsigned OpCode =
MI->getOpcode();
117 if (OpCode == SPIRV::OpDecorate) {
119 }
else if (OpCode == SPIRV::OpExtInstImport) {
120 recordOpExtInstImport(
MI);
121 }
else if (OpCode == SPIRV::OpExtInst) {
123 }
else if (OpCode == SPIRV::UNKNOWN_type) {
130 const unsigned LastFixedIndex = NumFixedOps - 1;
131 const int FirstVariableIndex = NumFixedOps;
132 if (NumFixedOps > 0 && MCDesc.
operands()[LastFixedIndex].OperandType ==
138 case SPIRV::OpTypeImage:
141 MI, FirstVariableIndex, OS);
143 case SPIRV::OpVariable:
147 case SPIRV::OpEntryPoint: {
153 case SPIRV::OpMemberDecorate:
156 case SPIRV::OpExecutionMode:
157 case SPIRV::OpExecutionModeId:
158 case SPIRV::OpLoopMerge:
159 case SPIRV::OpLoopControlINTEL: {
176 MI, FirstVariableIndex, OS);
179 case SPIRV::OpSwitch:
184 const unsigned NumOps =
MI->getNumOperands();
187 !
MI->getOperand(
OpIdx + 1).isImm()) {
194 uint64_t CombinedValue = (HighBits << 32) | LowBits;
209 case SPIRV::OpImageSampleImplicitLod:
210 case SPIRV::OpImageSampleDrefImplicitLod:
211 case SPIRV::OpImageSampleProjImplicitLod:
212 case SPIRV::OpImageSampleProjDrefImplicitLod:
213 case SPIRV::OpImageFetch:
214 case SPIRV::OpImageGather:
215 case SPIRV::OpImageDrefGather:
216 case SPIRV::OpImageRead:
217 case SPIRV::OpImageWrite:
218 case SPIRV::OpImageSparseSampleImplicitLod:
219 case SPIRV::OpImageSparseSampleDrefImplicitLod:
220 case SPIRV::OpImageSparseSampleProjImplicitLod:
221 case SPIRV::OpImageSparseSampleProjDrefImplicitLod:
222 case SPIRV::OpImageSparseFetch:
223 case SPIRV::OpImageSparseGather:
224 case SPIRV::OpImageSparseDrefGather:
225 case SPIRV::OpImageSparseRead:
226 case SPIRV::OpImageSampleFootprintNV:
229 MI, FirstVariableIndex, OS);
232 case SPIRV::OpCopyMemory:
233 case SPIRV::OpCopyMemorySized: {
234 const unsigned NumOps =
MI->getNumOperands();
235 for (
unsigned i = NumFixedOps; i <
NumOps; ++i) {
239 if (
MI->getOperand(i).getImm() & MemoryOperand::Aligned) {
248 case SPIRV::OpConstantI:
249 case SPIRV::OpConstantF:
252 assert(NumFixedOps > 0 &&
"Expected at least one fixed operand");
255 case SPIRV::OpCooperativeMatrixMulAddKHR: {
256 const unsigned NumOps =
MI->getNumOperands();
257 if (NumFixedOps ==
NumOps)
261 const unsigned MulAddOp =
MI->getOperand(FirstVariableIndex).getImm();
264 OperandCategory::CooperativeMatrixOperandsOperand>(
265 MI, FirstVariableIndex, OS);
268 for (
unsigned Mask = 0x1;
269 Mask != SPIRV::CooperativeMatrixOperands::
270 MatrixResultBFloat16ComponentsINTEL;
272 if (MulAddOp & Mask) {
276 OperandCategory::CooperativeMatrixOperandsOperand, Mask);
283 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
284 const unsigned NumOps =
MI->getNumOperands();
285 if (NumFixedOps >=
NumOps)
288 const unsigned Flags =
MI->getOperand(
NumOps - 1).getImm();
291 OperandCategory::MatrixMultiplyAccumulateOperandsOperand>(
295 for (
unsigned Mask = 0x1;
296 Mask <= SPIRV::MatrixMultiplyAccumulateOperands::
297 MatrixBPackedBFloat16INTEL;
303 OperandCategory::MatrixMultiplyAccumulateOperandsOperand,
314 case SPIRV::OpSDotAccSat:
315 case SPIRV::OpUDotAccSat:
316 case SPIRV::OpSUDotAccSat: {
317 const unsigned NumOps =
MI->getNumOperands();
318 if (
NumOps > NumFixedOps) {
326 case SPIRV::OpPredicatedLoadINTEL:
327 case SPIRV::OpPredicatedStoreINTEL: {
328 const unsigned NumOps =
MI->getNumOperands();
329 if (
NumOps > NumFixedOps) {
353 const auto NumOps =
MI->getNumOperands();
354 if (
NumOps == NumFixedOps)
369 if (NumFixedOps !=
MI->getNumOperands()) {
370 auto DecOp =
MI->getOperand(NumFixedOps - 1);
371 auto Dec =
static_cast<Decoration::Decoration
>(DecOp.getImm());
376 case Decoration::BuiltIn:
379 case Decoration::UniformId:
382 case Decoration::FuncParamAttr:
386 case Decoration::FPRoundingMode:
390 case Decoration::FPFastMathMode:
394 case Decoration::LinkageAttributes:
395 case Decoration::UserSemantic:
398 case Decoration::HostAccessINTEL:
400 if (NumFixedOps + 1 <
MI->getNumOperands()) {
413 const auto EnumOperand =
MI->getOperand(1);
414 assert(EnumOperand.isImm() &&
415 "second operand of UNKNOWN_type must be opcode!");
417 const auto Enumerant = EnumOperand.getImm();
418 const auto NumOps =
MI->getNumOperands();
421 O <<
"OpUnknown(" << Enumerant <<
", " <<
NumOps <<
") ";
430 if (
NumOps == NumFixedOps)
439 if (OpNo < MI->getNumOperands()) {
443 else if (
Op.isImm()) {
444 int64_t Imm =
Op.getImm();
449 if (
MI->getOpcode() == SPIRV::OpVectorShuffle && Imm == -1)
453 }
else if (
Op.isDFPImm())
455 else if (
Op.isExpr())
456 MAI.printExpr(O, *
Op.getExpr());
464 const unsigned NumOps =
MI->getNumOperands();
465 unsigned StrStartIndex = OpNo;
466 while (StrStartIndex <
NumOps) {
467 if (
MI->getOperand(StrStartIndex).isReg())
471 if (StrStartIndex != OpNo)
486 unsigned numOpsInString = (Str.size() / 4) + 1;
487 StrStartIndex += numOpsInString;
490 if (
MI->getOpcode() == SPIRV::OpDecorate &&
491 MI->getOperand(1).getImm() ==
492 static_cast<unsigned>(Decoration::LinkageAttributes)) {
495 MI, StrStartIndex, O);
503 auto SetReg =
MI->getOperand(2).getReg();
504 auto Set = ExtInstSetIDs[SetReg];
505 auto Op =
MI->getOperand(OpNo).getImm();
509template <OperandCategory::OperandCategory category>
512 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.
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