29#define DEBUG_TYPE "asm-printer"
32#include "SPIRVGenAsmWriter.inc"
38 bool SkipImmediates) {
39 const unsigned NumOps =
MI->getNumOperands();
40 for (
unsigned i = StartIndex; i <
NumOps; ++i) {
41 if (!SkipImmediates || !
MI->getOperand(i).isImm()) {
42 if (!SkipFirstSpace || i != StartIndex)
53 const unsigned NumVarOps =
MI->getNumOperands() - StartIndex;
55 if (
MI->getOpcode() == SPIRV::OpConstantI && NumVarOps > 2) {
59 unsigned Bitwidth = IntTypeBitwidths.at(IntTypeReg);
63 const unsigned TotalBits = NumVarOps * 32;
64 APInt Val(TotalBits, 0);
65 for (
unsigned i = 0; i < NumVarOps; ++i) {
66 uint64_t Word =
MI->getOperand(StartIndex + i).getImm();
67 Val |=
APInt(TotalBits, Word) << (i * 32);
71 ActualVal.
print(O,
false);
75 assert((NumVarOps == 1 || NumVarOps == 2) &&
76 "Unsupported number of bits for literal variable");
80 uint64_t Imm =
MI->getOperand(StartIndex).getImm();
84 Imm |= (
MI->getOperand(StartIndex + 1).
getImm() << 32);
88 if (
MI->getOpcode() == SPIRV::OpConstantF && IsBitwidth16 == 0) {
96 if (
FP.isInfinity() ||
FP.isNaN()) {
100 if (
FP.isInfinity()) {
101 O <<
"0x1p+" << MaxExp;
103 unsigned MantissaBits =
106 unsigned Pad =
alignTo(MantissaBits, 4) - MantissaBits;
107 std::string Hex =
utohexstr(Mantissa << Pad,
true,
108 (MantissaBits + Pad) / 4);
109 while (Hex.size() > 1 && Hex.back() ==
'0')
111 O <<
"0x1." << Hex <<
"p+" << MaxExp;
118 O <<
format(
"%.*g", std::numeric_limits<double>::max_digits10,
119 FP.convertToDouble());
131 if (OpNo >=
MI->getNumOperands())
133 const uint64_t Mask =
MI->getOperand(OpNo).getImm();
135 unsigned NextOp = OpNo + 1;
136 static constexpr uint64_t ParameterizedMasks[] = {
137 SPIRV::MemoryOperand::Aligned,
138 SPIRV::MemoryOperand::MakePointerAvailableKHR,
139 SPIRV::MemoryOperand::MakePointerVisibleKHR,
140 SPIRV::MemoryOperand::AliasScopeINTELMask,
141 SPIRV::MemoryOperand::NoAliasINTELMask,
143 for (
uint64_t ParamMask : ParameterizedMasks) {
144 if (!(Mask & ParamMask))
153void SPIRVInstPrinter::recordIntType(
const MCInst *
MI) {
155 unsigned Bitwidth =
MI->getOperand(1).getImm();
156 IntTypeBitwidths[IntTypeReg] = Bitwidth;
159void SPIRVInstPrinter::recordOpExtInstImport(
const MCInst *
MI) {
163 ExtInstSetIDs.insert({
Reg, Set});
169 const unsigned OpCode =
MI->getOpcode();
171 if (OpCode == SPIRV::OpTypeInt) {
175 if (OpCode == SPIRV::OpDecorate || OpCode == SPIRV::OpDecorateId) {
177 }
else if (OpCode == SPIRV::OpExtInstImport) {
178 recordOpExtInstImport(
MI);
179 }
else if (OpCode == SPIRV::OpExtInst) {
181 }
else if (OpCode == SPIRV::UNKNOWN_type) {
188 const unsigned LastFixedIndex = NumFixedOps - 1;
189 const int FirstVariableIndex = NumFixedOps;
190 if (NumFixedOps > 0 && MCDesc.
operands()[LastFixedIndex].OperandType ==
196 case SPIRV::OpTypeImage:
199 MI, FirstVariableIndex, OS);
201 case SPIRV::OpVariable:
205 case SPIRV::OpEntryPoint: {
211 case SPIRV::OpMemberDecorate:
214 case SPIRV::OpExecutionMode:
215 case SPIRV::OpExecutionModeId:
216 case SPIRV::OpLoopMerge:
217 case SPIRV::OpLoopControlINTEL: {
234 case SPIRV::OpSwitch:
239 const unsigned NumOps =
MI->getNumOperands();
240 for (
unsigned OpIdx = NumFixedOps; OpIdx <
NumOps;) {
241 if (OpIdx + 1 >=
NumOps || !
MI->getOperand(OpIdx).isImm() ||
242 !
MI->getOperand(OpIdx + 1).isImm()) {
247 uint64_t LowBits =
MI->getOperand(OpIdx).getImm();
248 uint64_t HighBits =
MI->getOperand(OpIdx + 1).getImm();
249 uint64_t CombinedValue = (HighBits << 32) | LowBits;
264 case SPIRV::OpImageSampleImplicitLod:
265 case SPIRV::OpImageSampleDrefImplicitLod:
266 case SPIRV::OpImageSampleProjImplicitLod:
267 case SPIRV::OpImageSampleProjDrefImplicitLod:
268 case SPIRV::OpImageFetch:
269 case SPIRV::OpImageGather:
270 case SPIRV::OpImageDrefGather:
271 case SPIRV::OpImageRead:
272 case SPIRV::OpImageWrite:
273 case SPIRV::OpImageSparseSampleImplicitLod:
274 case SPIRV::OpImageSparseSampleDrefImplicitLod:
275 case SPIRV::OpImageSparseSampleProjImplicitLod:
276 case SPIRV::OpImageSparseSampleProjDrefImplicitLod:
277 case SPIRV::OpImageSparseFetch:
278 case SPIRV::OpImageSparseGather:
279 case SPIRV::OpImageSparseDrefGather:
280 case SPIRV::OpImageSparseRead:
281 case SPIRV::OpImageSampleFootprintNV:
284 MI, FirstVariableIndex, OS);
287 case SPIRV::OpCopyMemory:
288 case SPIRV::OpCopyMemorySized: {
289 const unsigned NumOps =
MI->getNumOperands();
290 for (
unsigned i = NumFixedOps; i <
NumOps;)
294 case SPIRV::OpConstantI:
295 case SPIRV::OpConstantF:
298 assert(NumFixedOps > 0 &&
"Expected at least one fixed operand");
301 case SPIRV::OpCooperativeMatrixMulAddKHR: {
302 const unsigned NumOps =
MI->getNumOperands();
303 if (NumFixedOps ==
NumOps)
307 const unsigned MulAddOp =
MI->getOperand(FirstVariableIndex).getImm();
310 OperandCategory::CooperativeMatrixOperandsOperand>(
311 MI, FirstVariableIndex, OS);
314 for (
unsigned Mask = 0x1;
315 Mask != SPIRV::CooperativeMatrixOperands::
316 MatrixResultBFloat16ComponentsINTEL;
318 if (MulAddOp & Mask) {
322 OperandCategory::CooperativeMatrixOperandsOperand, Mask);
329 case SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL: {
330 const unsigned NumOps =
MI->getNumOperands();
331 if (NumFixedOps >=
NumOps)
334 const unsigned Flags =
MI->getOperand(
NumOps - 1).getImm();
337 OperandCategory::MatrixMultiplyAccumulateOperandsOperand>(
341 for (
unsigned Mask = 0x1;
342 Mask <= SPIRV::MatrixMultiplyAccumulateOperands::
343 MatrixBPackedBFloat16INTEL;
349 OperandCategory::MatrixMultiplyAccumulateOperandsOperand,
360 case SPIRV::OpSDotAccSat:
361 case SPIRV::OpUDotAccSat:
362 case SPIRV::OpSUDotAccSat: {
363 const unsigned NumOps =
MI->getNumOperands();
364 if (
NumOps > NumFixedOps) {
372 case SPIRV::OpPredicatedLoadINTEL:
373 case SPIRV::OpPredicatedStoreINTEL: {
374 if (
MI->getNumOperands() > NumFixedOps)
394 const auto NumOps =
MI->getNumOperands();
395 if (
NumOps == NumFixedOps)
410 if (NumFixedOps !=
MI->getNumOperands()) {
411 auto DecOp =
MI->getOperand(NumFixedOps - 1);
412 auto Dec =
static_cast<Decoration::Decoration
>(DecOp.getImm());
417 case Decoration::BuiltIn:
420 case Decoration::UniformId:
423 case Decoration::FuncParamAttr:
427 case Decoration::FPRoundingMode:
431 case Decoration::FPFastMathMode:
435 case Decoration::LinkageAttributes:
436 case Decoration::UserSemantic:
439 case Decoration::HostAccessINTEL:
441 if (NumFixedOps + 1 <
MI->getNumOperands()) {
454 const auto EnumOperand =
MI->getOperand(1);
455 assert(EnumOperand.isImm() &&
456 "second operand of UNKNOWN_type must be opcode!");
458 const auto Enumerant = EnumOperand.getImm();
459 const auto NumOps =
MI->getNumOperands();
462 O <<
"OpUnknown(" << Enumerant <<
", " <<
NumOps <<
") ";
471 if (
NumOps == NumFixedOps)
480 if (OpNo < MI->getNumOperands()) {
484 else if (
Op.isImm()) {
485 int64_t Imm =
Op.getImm();
490 if (
MI->getOpcode() == SPIRV::OpVectorShuffle && Imm == -1)
494 }
else if (
Op.isDFPImm())
496 else if (
Op.isExpr())
497 MAI.printExpr(O, *
Op.getExpr());
505 const unsigned NumOps =
MI->getNumOperands();
506 unsigned StrStartIndex = OpNo;
507 while (StrStartIndex <
NumOps) {
508 if (
MI->getOperand(StrStartIndex).isReg())
512 if (StrStartIndex != OpNo)
527 unsigned numOpsInString = (Str.size() / 4) + 1;
528 StrStartIndex += numOpsInString;
531 if (
MI->getOpcode() == SPIRV::OpDecorate &&
532 MI->getOperand(1).getImm() ==
533 static_cast<unsigned>(Decoration::LinkageAttributes)) {
536 MI, StrStartIndex, O);
544 auto SetReg =
MI->getOperand(2).getReg();
545 auto Set = ExtInstSetIDs[SetReg];
546 auto Op =
MI->getOperand(OpNo).getImm();
550template <OperandCategory::OperandCategory category>
553 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
static LLVM_ABI ExponentType semanticsMaxExponent(const fltSemantics &)
static LLVM_ABI unsigned int semanticsPrecision(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)
std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
std::string getSPIRVStringOperand(const InstType &MI, unsigned StartIndex)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
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
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.