Talvos  0.1
SPIR-V interpreter and dynamic analysis framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Instruction.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018 the Talvos developers. All rights reserved.
2 //
3 // This file is distributed under a three-clause BSD license. For full license
4 // terms please see the LICENSE file distributed with this source code.
5 
8 
9 #include <cassert>
10 #include <cstring>
11 #include <iostream>
12 #include <spirv/unified1/spirv.h>
13 
14 #include "talvos/Instruction.h"
15 
16 namespace talvos
17 {
18 
19 Instruction::Instruction(uint16_t Opcode, uint16_t NumOperands,
20  const uint32_t *Operands, const Type *ResultType)
21 {
22  this->Opcode = Opcode;
23  this->NumOperands = NumOperands;
24  this->ResultType = ResultType;
25  this->Next = nullptr;
26  this->Previous = nullptr;
27 
28  this->Operands = new uint32_t[NumOperands];
29  memcpy(this->Operands, Operands, NumOperands * sizeof(uint32_t));
30 }
31 
33 {
34  assert(Opcode != SpvOpLabel);
35 
36  this->Previous = I;
37  this->Next = std::move(I->Next);
38  if (this->Next)
39  this->Next->Previous = this;
40  I->Next = std::unique_ptr<Instruction>(this);
41 }
42 
43 void Instruction::print(std::ostream &O, bool Align) const
44 {
45  if (Align)
46  {
47  if (ResultType)
48  {
49  // TODO: Adapt extra whitespace based on module ID bound.
50  if (Operands[1] < 100)
51  O << " ";
52  if (Operands[1] < 10)
53  O << " ";
54  }
55  else
56  O << " ";
57  }
58 
59  if (ResultType)
60  O << "%" << Operands[1] << " = ";
61 
62  O << opcodeToString(Opcode);
63  for (unsigned i = 0; i < NumOperands; i++)
64  {
65  if (ResultType && i == 1)
66  continue;
67  // TODO: Omit the '%' if this is a literal operand.
68  O << " %" << Operands[i];
69  }
70 }
71 
72 const char *Instruction::opcodeToString(uint16_t Opcode)
73 {
74  // TODO: SPIRV-Tools might expose spvOpcodeString at some point.
75  switch (Opcode)
76  {
77 #define CASE(OP) \
78  case SpvOp##OP: \
79  return "Op" #OP
80 
81  CASE(Nop);
82  CASE(Undef);
83  CASE(SourceContinued);
84  CASE(Source);
85  CASE(SourceExtension);
86  CASE(Name);
87  CASE(MemberName);
88  CASE(String);
89  CASE(Line);
90  CASE(Extension);
91  CASE(ExtInstImport);
92  CASE(ExtInst);
93  CASE(MemoryModel);
95  CASE(ExecutionMode);
96  CASE(Capability);
97  CASE(TypeVoid);
98  CASE(TypeBool);
99  CASE(TypeInt);
100  CASE(TypeFloat);
101  CASE(TypeVector);
102  CASE(TypeMatrix);
103  CASE(TypeImage);
104  CASE(TypeSampler);
105  CASE(TypeSampledImage);
106  CASE(TypeArray);
107  CASE(TypeRuntimeArray);
108  CASE(TypeStruct);
109  CASE(TypeOpaque);
110  CASE(TypePointer);
111  CASE(TypeFunction);
112  CASE(TypeEvent);
113  CASE(TypeDeviceEvent);
114  CASE(TypeReserveId);
115  CASE(TypeQueue);
116  CASE(TypePipe);
117  CASE(TypeForwardPointer);
118  CASE(ConstantTrue);
119  CASE(ConstantFalse);
120  CASE(Constant);
121  CASE(ConstantComposite);
122  CASE(ConstantSampler);
123  CASE(ConstantNull);
124  CASE(SpecConstantTrue);
125  CASE(SpecConstantFalse);
126  CASE(SpecConstant);
127  CASE(SpecConstantComposite);
128  CASE(SpecConstantOp);
129  CASE(Function);
130  CASE(FunctionParameter);
131  CASE(FunctionEnd);
132  CASE(FunctionCall);
133  CASE(Variable);
134  CASE(ImageTexelPointer);
135  CASE(Load);
136  CASE(Store);
137  CASE(CopyMemory);
138  CASE(CopyMemorySized);
139  CASE(AccessChain);
140  CASE(InBoundsAccessChain);
141  CASE(PtrAccessChain);
142  CASE(ArrayLength);
143  CASE(GenericPtrMemSemantics);
144  CASE(InBoundsPtrAccessChain);
145  CASE(Decorate);
146  CASE(MemberDecorate);
147  CASE(DecorationGroup);
148  CASE(GroupDecorate);
149  CASE(GroupMemberDecorate);
150  CASE(VectorExtractDynamic);
151  CASE(VectorInsertDynamic);
152  CASE(VectorShuffle);
153  CASE(CompositeConstruct);
154  CASE(CompositeExtract);
155  CASE(CompositeInsert);
156  CASE(CopyObject);
157  CASE(Transpose);
159  CASE(ImageSampleImplicitLod);
160  CASE(ImageSampleExplicitLod);
161  CASE(ImageSampleDrefImplicitLod);
162  CASE(ImageSampleDrefExplicitLod);
163  CASE(ImageSampleProjImplicitLod);
164  CASE(ImageSampleProjExplicitLod);
165  CASE(ImageSampleProjDrefImplicitLod);
166  CASE(ImageSampleProjDrefExplicitLod);
167  CASE(ImageFetch);
168  CASE(ImageGather);
169  CASE(ImageDrefGather);
170  CASE(ImageRead);
171  CASE(ImageWrite);
172  CASE(Image);
173  CASE(ImageQueryFormat);
174  CASE(ImageQueryOrder);
175  CASE(ImageQuerySizeLod);
176  CASE(ImageQuerySize);
177  CASE(ImageQueryLod);
178  CASE(ImageQueryLevels);
179  CASE(ImageQuerySamples);
180  CASE(ConvertFToU);
181  CASE(ConvertFToS);
182  CASE(ConvertSToF);
183  CASE(ConvertUToF);
184  CASE(UConvert);
185  CASE(SConvert);
186  CASE(FConvert);
187  CASE(QuantizeToF16);
188  CASE(ConvertPtrToU);
189  CASE(SatConvertSToU);
190  CASE(SatConvertUToS);
191  CASE(ConvertUToPtr);
192  CASE(PtrCastToGeneric);
193  CASE(GenericCastToPtr);
194  CASE(GenericCastToPtrExplicit);
195  CASE(Bitcast);
196  CASE(SNegate);
197  CASE(FNegate);
198  CASE(IAdd);
199  CASE(FAdd);
200  CASE(ISub);
201  CASE(FSub);
202  CASE(IMul);
203  CASE(FMul);
204  CASE(UDiv);
205  CASE(SDiv);
206  CASE(FDiv);
207  CASE(UMod);
208  CASE(SRem);
209  CASE(SMod);
210  CASE(FRem);
211  CASE(FMod);
212  CASE(VectorTimesScalar);
213  CASE(MatrixTimesScalar);
214  CASE(VectorTimesMatrix);
215  CASE(MatrixTimesVector);
216  CASE(MatrixTimesMatrix);
217  CASE(OuterProduct);
218  CASE(Dot);
219  CASE(IAddCarry);
220  CASE(ISubBorrow);
221  CASE(UMulExtended);
222  CASE(SMulExtended);
223  CASE(Any);
224  CASE(All);
225  CASE(IsNan);
226  CASE(IsInf);
227  CASE(IsFinite);
228  CASE(IsNormal);
229  CASE(SignBitSet);
230  CASE(LessOrGreater);
231  CASE(Ordered);
232  CASE(Unordered);
233  CASE(LogicalEqual);
234  CASE(LogicalNotEqual);
235  CASE(LogicalOr);
236  CASE(LogicalAnd);
237  CASE(LogicalNot);
238  CASE(Select);
239  CASE(IEqual);
240  CASE(INotEqual);
241  CASE(UGreaterThan);
242  CASE(SGreaterThan);
243  CASE(UGreaterThanEqual);
244  CASE(SGreaterThanEqual);
245  CASE(ULessThan);
246  CASE(SLessThan);
247  CASE(ULessThanEqual);
248  CASE(SLessThanEqual);
249  CASE(FOrdEqual);
250  CASE(FUnordEqual);
251  CASE(FOrdNotEqual);
252  CASE(FUnordNotEqual);
253  CASE(FOrdLessThan);
254  CASE(FUnordLessThan);
255  CASE(FOrdGreaterThan);
256  CASE(FUnordGreaterThan);
257  CASE(FOrdLessThanEqual);
258  CASE(FUnordLessThanEqual);
259  CASE(FOrdGreaterThanEqual);
260  CASE(FUnordGreaterThanEqual);
261  CASE(ShiftRightLogical);
262  CASE(ShiftRightArithmetic);
263  CASE(ShiftLeftLogical);
264  CASE(BitwiseOr);
265  CASE(BitwiseXor);
266  CASE(BitwiseAnd);
267  CASE(Not);
268  CASE(BitFieldInsert);
269  CASE(BitFieldSExtract);
270  CASE(BitFieldUExtract);
271  CASE(BitReverse);
272  CASE(BitCount);
273  CASE(DPdx);
274  CASE(DPdy);
275  CASE(Fwidth);
276  CASE(DPdxFine);
277  CASE(DPdyFine);
278  CASE(FwidthFine);
279  CASE(DPdxCoarse);
280  CASE(DPdyCoarse);
281  CASE(FwidthCoarse);
282  CASE(EmitVertex);
283  CASE(EndPrimitive);
284  CASE(EmitStreamVertex);
285  CASE(EndStreamPrimitive);
286  CASE(ControlBarrier);
287  CASE(MemoryBarrier);
288  CASE(AtomicLoad);
289  CASE(AtomicStore);
290  CASE(AtomicExchange);
291  CASE(AtomicCompareExchange);
292  CASE(AtomicCompareExchangeWeak);
293  CASE(AtomicIIncrement);
294  CASE(AtomicIDecrement);
295  CASE(AtomicIAdd);
296  CASE(AtomicISub);
297  CASE(AtomicSMin);
298  CASE(AtomicUMin);
299  CASE(AtomicSMax);
300  CASE(AtomicUMax);
301  CASE(AtomicAnd);
302  CASE(AtomicOr);
303  CASE(AtomicXor);
304  CASE(Phi);
305  CASE(LoopMerge);
306  CASE(SelectionMerge);
307  CASE(Label);
308  CASE(Branch);
309  CASE(BranchConditional);
310  CASE(Switch);
311  CASE(Kill);
312  CASE(Return);
313  CASE(ReturnValue);
314  CASE(Unreachable);
315  CASE(LifetimeStart);
316  CASE(LifetimeStop);
317  CASE(GroupAsyncCopy);
318  CASE(GroupWaitEvents);
319  CASE(GroupAll);
320  CASE(GroupAny);
321  CASE(GroupBroadcast);
322  CASE(GroupIAdd);
323  CASE(GroupFAdd);
324  CASE(GroupFMin);
325  CASE(GroupUMin);
326  CASE(GroupSMin);
327  CASE(GroupFMax);
328  CASE(GroupUMax);
329  CASE(GroupSMax);
330  CASE(ReadPipe);
331  CASE(WritePipe);
332  CASE(ReservedReadPipe);
333  CASE(ReservedWritePipe);
334  CASE(ReserveReadPipePackets);
335  CASE(ReserveWritePipePackets);
336  CASE(CommitReadPipe);
337  CASE(CommitWritePipe);
338  CASE(IsValidReserveId);
339  CASE(GetNumPipePackets);
340  CASE(GetMaxPipePackets);
341  CASE(GroupReserveReadPipePackets);
342  CASE(GroupReserveWritePipePackets);
343  CASE(GroupCommitReadPipe);
344  CASE(GroupCommitWritePipe);
345  CASE(EnqueueMarker);
346  CASE(EnqueueKernel);
347  CASE(GetKernelNDrangeSubGroupCount);
348  CASE(GetKernelNDrangeMaxSubGroupSize);
349  CASE(GetKernelWorkGroupSize);
350  CASE(GetKernelPreferredWorkGroupSizeMultiple);
351  CASE(RetainEvent);
352  CASE(ReleaseEvent);
353  CASE(CreateUserEvent);
354  CASE(IsValidEvent);
355  CASE(SetUserEventStatus);
356  CASE(CaptureEventProfilingInfo);
357  CASE(GetDefaultQueue);
358  CASE(BuildNDRange);
359  CASE(ImageSparseSampleImplicitLod);
360  CASE(ImageSparseSampleExplicitLod);
361  CASE(ImageSparseSampleDrefImplicitLod);
362  CASE(ImageSparseSampleDrefExplicitLod);
363  CASE(ImageSparseSampleProjImplicitLod);
364  CASE(ImageSparseSampleProjExplicitLod);
365  CASE(ImageSparseSampleProjDrefImplicitLod);
366  CASE(ImageSparseSampleProjDrefExplicitLod);
367  CASE(ImageSparseFetch);
368  CASE(ImageSparseGather);
369  CASE(ImageSparseDrefGather);
370  CASE(ImageSparseTexelsResident);
371  CASE(NoLine);
372  CASE(AtomicFlagTestAndSet);
373  CASE(AtomicFlagClear);
374  CASE(ImageSparseRead);
375  CASE(SizeOf);
376  CASE(TypePipeStorage);
377  CASE(ConstantPipeStorage);
378  CASE(CreatePipeFromPipeStorage);
379  CASE(GetKernelLocalSizeForSubgroupCount);
380  CASE(GetKernelMaxNumSubgroups);
381  CASE(TypeNamedBarrier);
382  CASE(NamedBarrierInitialize);
383  CASE(MemoryNamedBarrier);
384  CASE(ModuleProcessed);
385  CASE(ExecutionModeId);
386  CASE(DecorateId);
387  CASE(SubgroupBallotKHR);
388  CASE(SubgroupFirstInvocationKHR);
389  CASE(SubgroupAllKHR);
390  CASE(SubgroupAnyKHR);
391  CASE(SubgroupAllEqualKHR);
392  CASE(SubgroupReadInvocationKHR);
393  CASE(GroupIAddNonUniformAMD);
394  CASE(GroupFAddNonUniformAMD);
395  CASE(GroupFMinNonUniformAMD);
396  CASE(GroupUMinNonUniformAMD);
397  CASE(GroupSMinNonUniformAMD);
398  CASE(GroupFMaxNonUniformAMD);
399  CASE(GroupUMaxNonUniformAMD);
400  CASE(GroupSMaxNonUniformAMD);
401  CASE(FragmentMaskFetchAMD);
402  CASE(FragmentFetchAMD);
403  CASE(SubgroupShuffleINTEL);
404  CASE(SubgroupShuffleDownINTEL);
405  CASE(SubgroupShuffleUpINTEL);
406  CASE(SubgroupShuffleXorINTEL);
407  CASE(SubgroupBlockReadINTEL);
408  CASE(SubgroupBlockWriteINTEL);
409  CASE(SubgroupImageBlockReadINTEL);
410  CASE(SubgroupImageBlockWriteINTEL);
411  default:
412  return "<invalid>";
413 
414 #undef CASE
415  }
416 }
417 
418 } // namespace talvos
This class represents a module-scope variable declaration.
Definition: Variable.h:21
uint16_t Opcode
The instruction opcode.
Definition: Instruction.h:85
This class represents an image object.
Definition: Image.h:24
A combination of an image and a sampler used to access it.
Definition: Image.h:268
std::unique_ptr< Instruction > Next
The next instruction in the block.
Definition: Instruction.h:89
This class represents a function in a SPIR-V Module.
Definition: Function.h:23
#define CASE(OP)
uint32_t * Operands
The operand values.
Definition: Instruction.h:87
void insertAfter(Instruction *I)
Insert this instruction into a sequence, immediately following I.
Definition: Instruction.cpp:32
const Type * ResultType
The type of the instruction result.
Definition: Instruction.h:84
This file declares the Instruction class.
Instruction(uint16_t Opcode, uint16_t NumOperands, const uint32_t *Operands, const Type *ResultType)
Create a new instruction.
Definition: Instruction.cpp:19
void print(std::ostream &O, bool Align=true) const
Print a human-readable form of this instruction to O.
Definition: Instruction.cpp:43
uint16_t NumOperands
The number of operands in this instruction.
Definition: Instruction.h:86
This class represents a SPIR-V type.
Definition: Type.h:33
This class represents a SPIR-V instruction.
Definition: Instruction.h:27
const Instruction * Previous
The previous instruction in the block.
Definition: Instruction.h:91
static const char * opcodeToString(uint16_t Opcode)
Return the string representation of an instruction opcode.
Definition: Instruction.cpp:72
This class represents a shader entry point.
Definition: EntryPoint.h:25