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) {
57 unsigned Bitwidth = IntTypeBitwidths.at(IntTypeReg);
61 const unsigned TotalBits = NumVarOps * 32;
62 APInt Val(TotalBits, 0);
63 for (
unsigned i = 0; i < NumVarOps; ++i) {
64 uint64_t Word =
MI->getOperand(StartIndex + i).getImm();
65 Val |=
APInt(TotalBits, Word) << (i * 32);
69 ActualVal.
print(O,
false);
73 assert((NumVarOps == 1 || NumVarOps == 2) &&
74 "Unsupported number of bits for literal variable");
78 uint64_t Imm =
MI->getOperand(StartIndex).getImm();
82 Imm |= (
MI->getOperand(StartIndex + 1).
getImm() << 32);
86 if (
MI->getOpcode() == SPIRV::OpConstantF && IsBitwidth16 == 0) {
93 if (
FP.isInfinity()) {
106 O <<
format(
"%.*g", std::numeric_limits<double>::max_digits10,
107 FP.convertToDouble());
116void SPIRVInstPrinter::recordIntType(
const MCInst *
MI) {
118 unsigned Bitwidth =
MI->getOperand(1).getImm();
119 IntTypeBitwidths[IntTypeReg] = Bitwidth;
122void SPIRVInstPrinter::recordOpExtInstImport(
const MCInst *
MI) {
126 ExtInstSetIDs.insert({
Reg, Set});
132 const unsigned OpCode =
MI->getOpcode();
134 if (OpCode == SPIRV::OpTypeInt) {
138 if (OpCode == SPIRV::OpDecorate) {
140 }
else if (OpCode == SPIRV::OpExtInstImport) {
141 recordOpExtInstImport(
MI);
142 }
else if (OpCode == SPIRV::OpExtInst) {
144 }
else if (OpCode == SPIRV::UNKNOWN_type) {
151 const unsigned LastFixedIndex = NumFixedOps - 1;
152 const int FirstVariableIndex = NumFixedOps;
153 if (NumFixedOps > 0 && MCDesc.
operands()[LastFixedIndex].OperandType ==
159 case SPIRV::OpTypeImage:
162 MI, FirstVariableIndex, OS);
164 case SPIRV::OpVariable:
168 case SPIRV::OpEntryPoint: {
174 case SPIRV::OpMemberDecorate:
177 case SPIRV::OpExecutionMode:
178 case SPIRV::OpExecutionModeId:
179 case SPIRV::OpLoopMerge:
180 case SPIRV::OpLoopControlINTEL: {
197 MI, FirstVariableIndex, OS);
200 case SPIRV::OpSwitch:
205 const unsigned NumOps =
MI->getNumOperands();
208 !
MI->getOperand(
OpIdx + 1).isImm()) {
215 uint64_t CombinedValue = (HighBits << 32) | LowBits;
230 case SPIRV::OpImageSampleImplicitLod:
231 case SPIRV::OpImageSampleDrefImplicitLod:
232 case SPIRV::OpImageSampleProjImplicitLod:
233 case SPIRV::OpImageSampleProjDrefImplicitLod:
234 case SPIRV::OpImageFetch:
235 case SPIRV::OpImageGather:
236 case SPIRV::OpImageDrefGather:
237 case SPIRV::OpImageRead:
238 case SPIRV::OpImageWrite:
239 case SPIRV::OpImageSparseSampleImplicitLod:
240 case SPIRV::OpImageSparseSampleDrefImplicitLod:
241 case SPIRV::OpImageSparseSampleProjImplicitLod:
242 case SPIRV::OpImageSparseSampleProjDrefImplicitLod:
243 case SPIRV::OpImageSparseFetch:
244 case SPIRV::OpImageSparseGather:
245 case SPIRV::OpImageSparseDrefGather:
246 case SPIRV::OpImageSparseRead:
247 case SPIRV::OpImageSampleFootprintNV:
250 MI, FirstVariableIndex, OS);
253 case SPIRV::OpCopyMemory:
254 case SPIRV::OpCopyMemorySized: {
255 const unsigned NumOps =
MI->getNumOperands();
256 for (
unsigned i = NumFixedOps; i <
NumOps; ++i) {
260 if (
MI->getOperand(i).getImm() & MemoryOperand::Aligned) {
269 case SPIRV::OpConstantI:
270 case SPIRV::OpConstantF:
273 assert(NumFixedOps > 0 &&
"Expected at least one fixed operand");
276 case SPIRV::OpCooperativeMatrixMulAddKHR: {
277 const unsigned NumOps =
MI->getNumOperands();
278 if (NumFixedOps ==
NumOps)
282 const unsigned MulAddOp =
MI->getOperand(FirstVariableIndex).getImm();
285 OperandCategory::CooperativeMatrixOperandsOperand>(
286 MI, FirstVariableIndex, OS);
289 for (
unsigned Mask = 0x1;
290 Mask != SPIRV::CooperativeMatrixOperands::
291 MatrixResultBFloat16ComponentsINTEL;
293 if (MulAddOp & Mask) {
297 OperandCategory::CooperativeMatrixOperandsOperand, Mask);
304 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
305 const unsigned NumOps =
MI->getNumOperands();
306 if (NumFixedOps >=
NumOps)
309 const unsigned Flags =
MI->getOperand(
NumOps - 1).getImm();
312 OperandCategory::MatrixMultiplyAccumulateOperandsOperand>(
316 for (
unsigned Mask = 0x1;
317 Mask <= SPIRV::MatrixMultiplyAccumulateOperands::
318 MatrixBPackedBFloat16INTEL;
324 OperandCategory::MatrixMultiplyAccumulateOperandsOperand,
335 case SPIRV::OpSDotAccSat:
336 case SPIRV::OpUDotAccSat:
337 case SPIRV::OpSUDotAccSat: {
338 const unsigned NumOps =
MI->getNumOperands();
339 if (
NumOps > NumFixedOps) {
347 case SPIRV::OpPredicatedLoadINTEL:
348 case SPIRV::OpPredicatedStoreINTEL: {
349 const unsigned NumOps =
MI->getNumOperands();
350 if (
NumOps > NumFixedOps) {
374 const auto NumOps =
MI->getNumOperands();
375 if (
NumOps == NumFixedOps)
390 if (NumFixedOps !=
MI->getNumOperands()) {
391 auto DecOp =
MI->getOperand(NumFixedOps - 1);
392 auto Dec =
static_cast<Decoration::Decoration
>(DecOp.getImm());
397 case Decoration::BuiltIn:
400 case Decoration::UniformId:
403 case Decoration::FuncParamAttr:
407 case Decoration::FPRoundingMode:
411 case Decoration::FPFastMathMode:
415 case Decoration::LinkageAttributes:
416 case Decoration::UserSemantic:
419 case Decoration::HostAccessINTEL:
421 if (NumFixedOps + 1 <
MI->getNumOperands()) {
434 const auto EnumOperand =
MI->getOperand(1);
435 assert(EnumOperand.isImm() &&
436 "second operand of UNKNOWN_type must be opcode!");
438 const auto Enumerant = EnumOperand.getImm();
439 const auto NumOps =
MI->getNumOperands();
442 O <<
"OpUnknown(" << Enumerant <<
", " <<
NumOps <<
") ";
451 if (
NumOps == NumFixedOps)
460 if (OpNo < MI->getNumOperands()) {
464 else if (
Op.isImm()) {
465 int64_t Imm =
Op.getImm();
470 if (
MI->getOpcode() == SPIRV::OpVectorShuffle && Imm == -1)
474 }
else if (
Op.isDFPImm())
476 else if (
Op.isExpr())
477 MAI.printExpr(O, *
Op.getExpr());
485 const unsigned NumOps =
MI->getNumOperands();
486 unsigned StrStartIndex = OpNo;
487 while (StrStartIndex <
NumOps) {
488 if (
MI->getOperand(StrStartIndex).isReg())
492 if (StrStartIndex != OpNo)
507 unsigned numOpsInString = (Str.size() / 4) + 1;
508 StrStartIndex += numOpsInString;
511 if (
MI->getOpcode() == SPIRV::OpDecorate &&
512 MI->getOperand(1).getImm() ==
513 static_cast<unsigned>(Decoration::LinkageAttributes)) {
516 MI, StrStartIndex, O);
524 auto SetReg =
MI->getOperand(2).getReg();
525 auto Set = ExtInstSetIDs[SetReg];
526 auto Op =
MI->getOperand(OpNo).getImm();
530template <OperandCategory::OperandCategory category>
533 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.
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)
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