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:
132 printSymbolicOperand<OperandCategory::AccessQualifierOperand>(
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: {
166 printSymbolicOperand<OperandCategory::MemoryOperandOperand>(
167 MI, FirstVariableIndex,
OS);
170 case SPIRV::OpImageSampleImplicitLod:
171 case SPIRV::OpImageSampleDrefImplicitLod:
172 case SPIRV::OpImageSampleProjImplicitLod:
173 case SPIRV::OpImageSampleProjDrefImplicitLod:
174 case SPIRV::OpImageFetch:
175 case SPIRV::OpImageGather:
176 case SPIRV::OpImageDrefGather:
177 case SPIRV::OpImageRead:
178 case SPIRV::OpImageWrite:
179 case SPIRV::OpImageSparseSampleImplicitLod:
180 case SPIRV::OpImageSparseSampleDrefImplicitLod:
181 case SPIRV::OpImageSparseSampleProjImplicitLod:
182 case SPIRV::OpImageSparseSampleProjDrefImplicitLod:
183 case SPIRV::OpImageSparseFetch:
184 case SPIRV::OpImageSparseGather:
185 case SPIRV::OpImageSparseDrefGather:
186 case SPIRV::OpImageSparseRead:
187 case SPIRV::OpImageSampleFootprintNV:
189 printSymbolicOperand<OperandCategory::ImageOperandOperand>(
190 MI, FirstVariableIndex,
OS);
193 case SPIRV::OpCopyMemory:
194 case SPIRV::OpCopyMemorySized: {
195 const unsigned NumOps =
MI->getNumOperands();
196 for (
unsigned i = NumFixedOps; i < NumOps; ++i) {
198 printSymbolicOperand<OperandCategory::MemoryOperandOperand>(
MI, i,
200 if (
MI->getOperand(i).getImm() & MemoryOperand::Aligned) {
201 assert(i + 1 < NumOps &&
"Missing alignment operand");
209 case SPIRV::OpConstantI:
210 case SPIRV::OpConstantF:
213 assert(NumFixedOps > 0 &&
"Expected at least one fixed operand");
216 case SPIRV::OpCooperativeMatrixMulAddKHR: {
217 const unsigned NumOps =
MI->getNumOperands();
218 if (NumFixedOps == NumOps)
222 const unsigned MulAddOp =
MI->getOperand(FirstVariableIndex).getImm();
225 OperandCategory::CooperativeMatrixOperandsOperand>(
226 MI, FirstVariableIndex,
OS);
229 for (
unsigned Mask = 0x1;
230 Mask != SPIRV::CooperativeMatrixOperands::
231 MatrixResultBFloat16ComponentsINTEL;
233 if (MulAddOp & Mask) {
237 OperandCategory::CooperativeMatrixOperandsOperand, Mask);
244 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
245 const unsigned NumOps =
MI->getNumOperands();
246 if (NumFixedOps >= NumOps)
249 const unsigned Flags =
MI->getOperand(NumOps - 1).getImm();
252 OperandCategory::MatrixMultiplyAccumulateOperandsOperand>(
256 for (
unsigned Mask = 0x1;
257 Mask <= SPIRV::MatrixMultiplyAccumulateOperands::
258 MatrixBPackedBFloat16INTEL;
264 OperandCategory::MatrixMultiplyAccumulateOperandsOperand,
288 const auto NumOps =
MI->getNumOperands();
289 if (NumOps == NumFixedOps)
304 if (NumFixedOps !=
MI->getNumOperands()) {
305 auto DecOp =
MI->getOperand(NumFixedOps - 1);
306 auto Dec =
static_cast<Decoration::Decoration
>(DecOp.getImm());
311 case Decoration::BuiltIn:
312 printSymbolicOperand<OperandCategory::BuiltInOperand>(
MI, NumFixedOps, O);
314 case Decoration::UniformId:
315 printSymbolicOperand<OperandCategory::ScopeOperand>(
MI, NumFixedOps, O);
317 case Decoration::FuncParamAttr:
318 printSymbolicOperand<OperandCategory::FunctionParameterAttributeOperand>(
321 case Decoration::FPRoundingMode:
322 printSymbolicOperand<OperandCategory::FPRoundingModeOperand>(
325 case Decoration::FPFastMathMode:
326 printSymbolicOperand<OperandCategory::FPFastMathModeOperand>(
329 case Decoration::LinkageAttributes:
330 case Decoration::UserSemantic:
333 case Decoration::HostAccessINTEL:
335 if (NumFixedOps + 1 <
MI->getNumOperands()) {
348 const auto EnumOperand =
MI->getOperand(1);
349 assert(EnumOperand.isImm() &&
350 "second operand of UNKNOWN_type must be opcode!");
352 const auto Enumerant = EnumOperand.getImm();
353 const auto NumOps =
MI->getNumOperands();
356 O <<
"OpUnknown(" << Enumerant <<
", " << NumOps <<
") ";
365 if (NumOps == NumFixedOps)
374 if (OpNo < MI->getNumOperands()) {
378 else if (
Op.isImm()) {
379 int64_t Imm =
Op.getImm();
384 if (
MI->getOpcode() == SPIRV::OpVectorShuffle && Imm == -1)
388 }
else if (
Op.isDFPImm())
390 else if (
Op.isExpr())
399 const unsigned NumOps =
MI->getNumOperands();
400 unsigned StrStartIndex = OpNo;
401 while (StrStartIndex < NumOps) {
402 if (
MI->getOperand(StrStartIndex).isReg())
406 if (StrStartIndex != OpNo)
421 unsigned numOpsInString = (Str.size() / 4) + 1;
422 StrStartIndex += numOpsInString;
425 if (
MI->getOpcode() == SPIRV::OpDecorate &&
426 MI->getOperand(1).getImm() ==
427 static_cast<unsigned>(Decoration::LinkageAttributes)) {
429 printSymbolicOperand<OperandCategory::LinkageTypeOperand>(
430 MI, StrStartIndex, O);
438 auto SetReg =
MI->getOperand(2).getReg();
439 auto Set = ExtInstSetIDs[SetReg];
440 auto Op =
MI->getOperand(OpNo).getImm();
444template <OperandCategory::OperandCategory category>
447 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...
Class for arbitrary precision integers.
This class represents an Operation in the Expression.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
void printExpr(raw_ostream &, const MCExpr &) 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.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
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)
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)