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) {
94 if (
FP.isInfinity() ||
FP.isNaN()) {
96 if (
FP.isInfinity()) {
99 O <<
"0x1p+" << MaxExp;
101 O <<
"0x1.8p+" << MaxExp;
108 O <<
format(
"%.*g", std::numeric_limits<double>::max_digits10,
109 FP.convertToDouble());
121 if (OpNo >=
MI->getNumOperands())
123 const uint64_t Mask =
MI->getOperand(OpNo).getImm();
125 unsigned NextOp = OpNo + 1;
126 static constexpr uint64_t ParameterizedMasks[] = {
127 SPIRV::MemoryOperand::Aligned,
128 SPIRV::MemoryOperand::MakePointerAvailableKHR,
129 SPIRV::MemoryOperand::MakePointerVisibleKHR,
130 SPIRV::MemoryOperand::AliasScopeINTELMask,
131 SPIRV::MemoryOperand::NoAliasINTELMask,
133 for (
uint64_t ParamMask : ParameterizedMasks) {
134 if (!(Mask & ParamMask))
143void SPIRVInstPrinter::recordIntType(
const MCInst *
MI) {
145 unsigned Bitwidth =
MI->getOperand(1).getImm();
146 IntTypeBitwidths[IntTypeReg] = Bitwidth;
149void SPIRVInstPrinter::recordOpExtInstImport(
const MCInst *
MI) {
153 ExtInstSetIDs.insert({
Reg, Set});
159 const unsigned OpCode =
MI->getOpcode();
161 if (OpCode == SPIRV::OpTypeInt) {
165 if (OpCode == SPIRV::OpDecorate || OpCode == SPIRV::OpDecorateId) {
167 }
else if (OpCode == SPIRV::OpExtInstImport) {
168 recordOpExtInstImport(
MI);
169 }
else if (OpCode == SPIRV::OpExtInst) {
171 }
else if (OpCode == SPIRV::UNKNOWN_type) {
178 const unsigned LastFixedIndex = NumFixedOps - 1;
179 const int FirstVariableIndex = NumFixedOps;
180 if (NumFixedOps > 0 && MCDesc.
operands()[LastFixedIndex].OperandType ==
186 case SPIRV::OpTypeImage:
189 MI, FirstVariableIndex, OS);
191 case SPIRV::OpVariable:
195 case SPIRV::OpEntryPoint: {
201 case SPIRV::OpMemberDecorate:
204 case SPIRV::OpExecutionMode:
205 case SPIRV::OpExecutionModeId:
206 case SPIRV::OpLoopMerge:
207 case SPIRV::OpLoopControlINTEL: {
224 case SPIRV::OpSwitch:
229 const unsigned NumOps =
MI->getNumOperands();
232 !
MI->getOperand(
OpIdx + 1).isImm()) {
239 uint64_t CombinedValue = (HighBits << 32) | LowBits;
254 case SPIRV::OpImageSampleImplicitLod:
255 case SPIRV::OpImageSampleDrefImplicitLod:
256 case SPIRV::OpImageSampleProjImplicitLod:
257 case SPIRV::OpImageSampleProjDrefImplicitLod:
258 case SPIRV::OpImageFetch:
259 case SPIRV::OpImageGather:
260 case SPIRV::OpImageDrefGather:
261 case SPIRV::OpImageRead:
262 case SPIRV::OpImageWrite:
263 case SPIRV::OpImageSparseSampleImplicitLod:
264 case SPIRV::OpImageSparseSampleDrefImplicitLod:
265 case SPIRV::OpImageSparseSampleProjImplicitLod:
266 case SPIRV::OpImageSparseSampleProjDrefImplicitLod:
267 case SPIRV::OpImageSparseFetch:
268 case SPIRV::OpImageSparseGather:
269 case SPIRV::OpImageSparseDrefGather:
270 case SPIRV::OpImageSparseRead:
271 case SPIRV::OpImageSampleFootprintNV:
274 MI, FirstVariableIndex, OS);
277 case SPIRV::OpCopyMemory:
278 case SPIRV::OpCopyMemorySized: {
279 const unsigned NumOps =
MI->getNumOperands();
280 for (
unsigned i = NumFixedOps; i <
NumOps;)
284 case SPIRV::OpConstantI:
285 case SPIRV::OpConstantF:
288 assert(NumFixedOps > 0 &&
"Expected at least one fixed operand");
291 case SPIRV::OpCooperativeMatrixMulAddKHR: {
292 const unsigned NumOps =
MI->getNumOperands();
293 if (NumFixedOps ==
NumOps)
297 const unsigned MulAddOp =
MI->getOperand(FirstVariableIndex).getImm();
300 OperandCategory::CooperativeMatrixOperandsOperand>(
301 MI, FirstVariableIndex, OS);
304 for (
unsigned Mask = 0x1;
305 Mask != SPIRV::CooperativeMatrixOperands::
306 MatrixResultBFloat16ComponentsINTEL;
308 if (MulAddOp & Mask) {
312 OperandCategory::CooperativeMatrixOperandsOperand, Mask);
319 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
320 const unsigned NumOps =
MI->getNumOperands();
321 if (NumFixedOps >=
NumOps)
324 const unsigned Flags =
MI->getOperand(
NumOps - 1).getImm();
327 OperandCategory::MatrixMultiplyAccumulateOperandsOperand>(
331 for (
unsigned Mask = 0x1;
332 Mask <= SPIRV::MatrixMultiplyAccumulateOperands::
333 MatrixBPackedBFloat16INTEL;
339 OperandCategory::MatrixMultiplyAccumulateOperandsOperand,
350 case SPIRV::OpSDotAccSat:
351 case SPIRV::OpUDotAccSat:
352 case SPIRV::OpSUDotAccSat: {
353 const unsigned NumOps =
MI->getNumOperands();
354 if (
NumOps > NumFixedOps) {
362 case SPIRV::OpPredicatedLoadINTEL:
363 case SPIRV::OpPredicatedStoreINTEL: {
364 if (
MI->getNumOperands() > NumFixedOps)
384 const auto NumOps =
MI->getNumOperands();
385 if (
NumOps == NumFixedOps)
400 if (NumFixedOps !=
MI->getNumOperands()) {
401 auto DecOp =
MI->getOperand(NumFixedOps - 1);
402 auto Dec =
static_cast<Decoration::Decoration
>(DecOp.getImm());
407 case Decoration::BuiltIn:
410 case Decoration::UniformId:
413 case Decoration::FuncParamAttr:
417 case Decoration::FPRoundingMode:
421 case Decoration::FPFastMathMode:
425 case Decoration::LinkageAttributes:
426 case Decoration::UserSemantic:
429 case Decoration::HostAccessINTEL:
431 if (NumFixedOps + 1 <
MI->getNumOperands()) {
444 const auto EnumOperand =
MI->getOperand(1);
445 assert(EnumOperand.isImm() &&
446 "second operand of UNKNOWN_type must be opcode!");
448 const auto Enumerant = EnumOperand.getImm();
449 const auto NumOps =
MI->getNumOperands();
452 O <<
"OpUnknown(" << Enumerant <<
", " <<
NumOps <<
") ";
461 if (
NumOps == NumFixedOps)
470 if (OpNo < MI->getNumOperands()) {
474 else if (
Op.isImm()) {
475 int64_t Imm =
Op.getImm();
480 if (
MI->getOpcode() == SPIRV::OpVectorShuffle && Imm == -1)
484 }
else if (
Op.isDFPImm())
486 else if (
Op.isExpr())
487 MAI.printExpr(O, *
Op.getExpr());
495 const unsigned NumOps =
MI->getNumOperands();
496 unsigned StrStartIndex = OpNo;
497 while (StrStartIndex <
NumOps) {
498 if (
MI->getOperand(StrStartIndex).isReg())
502 if (StrStartIndex != OpNo)
517 unsigned numOpsInString = (Str.size() / 4) + 1;
518 StrStartIndex += numOpsInString;
521 if (
MI->getOpcode() == SPIRV::OpDecorate &&
522 MI->getOperand(1).getImm() ==
523 static_cast<unsigned>(Decoration::LinkageAttributes)) {
526 MI, StrStartIndex, O);
534 auto SetReg =
MI->getOperand(2).getReg();
535 auto Set = ExtInstSetIDs[SetReg];
536 auto Op =
MI->getOperand(OpNo).getImm();
540template <OperandCategory::OperandCategory category>
543 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
static LLVM_ABI ExponentType semanticsMaxExponent(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)
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