blob: 74f0b42873d1c18bfdedf6110777ad880fd58e1f [file] [log] [blame]
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +01001// Copyright (c) 2015 The Khronos Group Inc.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and/or associated documentation files (the
5// "Materials"), to deal in the Materials without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Materials, and to
8// permit persons to whom the Materials are furnished to do so, subject to
9// the following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Materials.
13//
14// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
15// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
16// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
17// https://www.khronos.org/registry/
18//
19// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
26
27#include <libspirv/libspirv.h>
David Netodb901b62015-10-27 16:14:40 -040028#include "endian.h"
David Netob5dc8fc2015-10-06 16:22:00 -040029#include "instruction.h"
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010030#include "opcode.h"
31
32#include <assert.h>
33#include <string.h>
34
David Neto78c3b432015-08-27 13:03:52 -040035namespace {
36
37// Descriptions of each opcode. Each entry describes the format of the
38// instruction that follows a particular opcode.
39//
40// Most fields are initialized statically by including an automatically
41// generated file.
42// The operandTypes fields are initialized during spvOpcodeInitialize().
43//
44// TODO(dneto): Some of the macros are quite unreadable. We could make
45// good use of constexpr functions, but some compilers don't support that yet.
46spv_opcode_desc_t opcodeTableEntries[] = {
47#define EmptyList {}
48#define List(...) {__VA_ARGS__}
Lei Zhangb36e7042015-10-28 13:40:52 -040049#define Capability(X) SPV_CAPABILITY_AS_MASK(SpvCapability##X)
Dejan Mircevski205408b2015-09-30 16:42:34 -040050#define Capability2(X,Y) Capability(X)|Capability(Y)
Lei Zhangb36e7042015-10-28 13:40:52 -040051#define SpvCapabilityNone 0 // Needed so Capability(None) still expands to valid syntax.
David Neto78c3b432015-08-27 13:03:52 -040052#define Instruction(Name,HasResult,HasType,NumLogicalOperands,NumCapabilities,CapabilityRequired,IsVariable,LogicalArgsList) \
53 { #Name, \
Lei Zhangb36e7042015-10-28 13:40:52 -040054 SpvOp##Name, \
Dejan Mircevski205408b2015-09-30 16:42:34 -040055 (NumCapabilities) ? (CapabilityRequired) : 0, \
David Neto78c3b432015-08-27 13:03:52 -040056 0, {}, /* Filled in later. Operand list, including result id and type id, if needed */ \
57 HasResult, \
58 HasType, \
59 LogicalArgsList },
60#include "opcode.inc"
61#undef EmptyList
62#undef List
63#undef Capability
Dejan Mircevski205408b2015-09-30 16:42:34 -040064#undef Capability2
David Neto78c3b432015-08-27 13:03:52 -040065#undef CapabilityNone
66#undef Instruction
67};
68
69// Has the opcodeTableEntries table been fully elaborated?
70// That is, are the operandTypes fields initialized?
71bool opcodeTableInitialized = false;
72
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010073// Opcode API
74
David Neto78c3b432015-08-27 13:03:52 -040075// Converts the given operand class enum (from the SPIR-V document generation
76// logic) to the operand type required by the parser.
77// This only applies to logical operands.
Lei Zhangb36e7042015-10-28 13:40:52 -040078spv_operand_type_t convertOperandClassToType(SpvOp opcode,
79 OperandClass operandClass) {
David Neto78c3b432015-08-27 13:03:52 -040080 // The spec document generator uses OptionalOperandLiteral for several kinds
81 // of repeating values. Our parser needs more specific information about
82 // what is being repeated.
83 if (operandClass == OperandOptionalLiteral) {
Lei Zhang40056702015-09-11 14:31:27 -040084 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -040085 case SpvOpLoad:
86 case SpvOpStore:
87 case SpvOpCopyMemory:
88 case SpvOpCopyMemorySized:
David Neto3fca4cd2015-09-17 17:39:45 -040089 // Expect an optional mask. When the Aligned bit is set in the mask,
90 // we will later add the expectation of a literal number operand.
91 return SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS;
Lei Zhangb36e7042015-10-28 13:40:52 -040092 case SpvOpExecutionMode:
David Neto78c3b432015-08-27 13:03:52 -040093 return SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE;
94 default:
95 break;
96 }
Lei Zhangb41d1502015-09-14 15:22:23 -040097 } else if (operandClass == OperandVariableLiterals) {
Lei Zhangb36e7042015-10-28 13:40:52 -040098 if (opcode == SpvOpConstant || opcode == SpvOpSpecConstant)
Lei Zhangb41d1502015-09-14 15:22:23 -040099 return SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER;
David Neto78c3b432015-08-27 13:03:52 -0400100 }
101
102 switch(operandClass) {
103 case OperandNone: return SPV_OPERAND_TYPE_NONE;
104 case OperandId: return SPV_OPERAND_TYPE_ID;
105 case OperandOptionalId: return SPV_OPERAND_TYPE_OPTIONAL_ID;
David Neto561dc4e2015-09-25 14:23:29 -0400106 case OperandOptionalImage: return SPV_OPERAND_TYPE_OPTIONAL_IMAGE;
David Neto78c3b432015-08-27 13:03:52 -0400107 case OperandVariableIds: return SPV_OPERAND_TYPE_VARIABLE_ID;
David Neto561dc4e2015-09-25 14:23:29 -0400108 // The spec only uses OptionalLiteral for an optional literal number.
Lei Zhang6483bd72015-10-14 17:02:39 -0400109 case OperandOptionalLiteral: return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER;
David Neto78c3b432015-08-27 13:03:52 -0400110 case OperandOptionalLiteralString: return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING;
David Neto561dc4e2015-09-25 14:23:29 -0400111 // This is only used for sequences of literal numbers.
Lei Zhang6483bd72015-10-14 17:02:39 -0400112 case OperandVariableLiterals: return SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER;
David Neto445ce442015-10-15 15:22:06 -0400113 case OperandLiteralNumber:
Lei Zhangb36e7042015-10-28 13:40:52 -0400114 if (opcode == SpvOpExtInst) {
David Neto445ce442015-10-15 15:22:06 -0400115 // We use a special operand type for the extension instruction number.
116 // For now, we assume there is only one LiteraNumber argument to OpExtInst,
117 // and it is the extension instruction argument.
118 // See the ExtInst entry in opcode.inc
119 // TODO(dneto): Use a function to confirm the assumption, and to verify
120 // that the index into the operandClass is 1, as expected.
121 return SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER;
122 }
123 return SPV_OPERAND_TYPE_LITERAL_INTEGER;
David Neto78c3b432015-08-27 13:03:52 -0400124 case OperandLiteralString: return SPV_OPERAND_TYPE_LITERAL_STRING;
125 case OperandSource: return SPV_OPERAND_TYPE_SOURCE_LANGUAGE;
126 case OperandExecutionModel: return SPV_OPERAND_TYPE_EXECUTION_MODEL;
127 case OperandAddressing: return SPV_OPERAND_TYPE_ADDRESSING_MODEL;
128 case OperandMemory: return SPV_OPERAND_TYPE_MEMORY_MODEL;
129 case OperandExecutionMode: return SPV_OPERAND_TYPE_EXECUTION_MODE;
130 case OperandStorage: return SPV_OPERAND_TYPE_STORAGE_CLASS;
131 case OperandDimensionality: return SPV_OPERAND_TYPE_DIMENSIONALITY;
132 case OperandSamplerAddressingMode: return SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE;
133 case OperandSamplerFilterMode: return SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE;
David Netob30a0c52015-09-16 15:56:43 -0400134 case OperandSamplerImageFormat: return SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT;
David Neto7cefb232015-09-28 15:33:49 -0400135 case OperandImageChannelOrder:
136 // This is only used to describe the value generated by OpImageQueryOrder.
137 // It is not used as an operand.
138 break;
139 case OperandImageChannelDataType:
140 // This is only used to describe the value generated by OpImageQueryFormat.
141 // It is not used as an operand.
142 break;
143 case OperandImageOperands:
Dejan Mircevskif8e091a2015-10-13 14:41:31 -0400144 // This is not used in opcode.inc. It only exists to generate the
145 // corresponding spec section. In parsing, image operands meld into the
146 // OperandOptionalImage case.
David Neto7cefb232015-09-28 15:33:49 -0400147 break;
David Neto78c3b432015-08-27 13:03:52 -0400148 case OperandFPFastMath: return SPV_OPERAND_TYPE_FP_FAST_MATH_MODE;
149 case OperandFPRoundingMode: return SPV_OPERAND_TYPE_FP_ROUNDING_MODE;
150 case OperandLinkageType: return SPV_OPERAND_TYPE_LINKAGE_TYPE;
151 case OperandAccessQualifier: return SPV_OPERAND_TYPE_ACCESS_QUALIFIER;
152 case OperandFuncParamAttr: return SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE;
153 case OperandDecoration: return SPV_OPERAND_TYPE_DECORATION;
154 case OperandBuiltIn: return SPV_OPERAND_TYPE_BUILT_IN;
155 case OperandSelect: return SPV_OPERAND_TYPE_SELECTION_CONTROL;
156 case OperandLoop: return SPV_OPERAND_TYPE_LOOP_CONTROL;
157 case OperandFunction: return SPV_OPERAND_TYPE_FUNCTION_CONTROL;
158 case OperandMemorySemantics: return SPV_OPERAND_TYPE_MEMORY_SEMANTICS;
159 case OperandMemoryAccess:
David Neto7cefb232015-09-28 15:33:49 -0400160 // This case does not occur in the table for SPIR-V 0.99 Rev 32.
David Neto3fca4cd2015-09-17 17:39:45 -0400161 // We expect that it will become SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
David Neto78c3b432015-08-27 13:03:52 -0400162 // and we can remove the special casing above for memory operation
163 // instructions.
164 break;
165 case OperandScope: return SPV_OPERAND_TYPE_EXECUTION_SCOPE;
166 case OperandGroupOperation: return SPV_OPERAND_TYPE_GROUP_OPERATION;
167 case OperandKernelEnqueueFlags: return SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS;
168 case OperandKernelProfilingInfo: return SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO;
169 case OperandCapability: return SPV_OPERAND_TYPE_CAPABILITY;
170
171 // Used by GroupMemberDecorate
Lei Zhang6483bd72015-10-14 17:02:39 -0400172 case OperandVariableIdLiteral: return SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER;
David Neto78c3b432015-08-27 13:03:52 -0400173
174 // Used by Switch
Lei Zhang6483bd72015-10-14 17:02:39 -0400175 case OperandVariableLiteralId: return SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID;
David Neto78c3b432015-08-27 13:03:52 -0400176
177 // These exceptional cases shouldn't occur.
178 case OperandCount:
179 default:
180 break;
181 }
182 assert(0 && "Unexpected operand class");
183 return SPV_OPERAND_TYPE_NONE;
184}
185
Lei Zhanga94701d2015-09-14 10:05:37 -0400186} // anonymous namespace
David Neto78c3b432015-08-27 13:03:52 -0400187
188// Finish populating the opcodeTableEntries array.
189void spvOpcodeTableInitialize() {
190 // Compute the operandTypes field for each entry.
Lei Zhanga94701d2015-09-14 10:05:37 -0400191 for (auto &opcode : opcodeTableEntries) {
David Neto78c3b432015-08-27 13:03:52 -0400192 opcode.numTypes = 0;
193 // Type ID always comes first, if present.
194 if (opcode.hasType)
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400195 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_TYPE_ID;
David Neto78c3b432015-08-27 13:03:52 -0400196 // Result ID always comes next, if present
197 if (opcode.hasResult)
198 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_RESULT_ID;
Lei Zhanga94701d2015-09-14 10:05:37 -0400199 const uint16_t maxNumOperands =
200 sizeof(opcode.operandTypes) / sizeof(opcode.operandTypes[0]);
201 const uint16_t maxNumClasses =
202 sizeof(opcode.operandClass) / sizeof(opcode.operandClass[0]);
203 for (uint16_t classIndex = 0;
204 opcode.numTypes < maxNumOperands && classIndex < maxNumClasses;
205 classIndex++) {
David Neto78c3b432015-08-27 13:03:52 -0400206 const OperandClass operandClass = opcode.operandClass[classIndex];
Lei Zhanga94701d2015-09-14 10:05:37 -0400207 opcode.operandTypes[opcode.numTypes++] =
208 convertOperandClassToType(opcode.opcode, operandClass);
David Neto78c3b432015-08-27 13:03:52 -0400209 // The OperandNone value is not explicitly represented in the .inc file.
210 // However, it is the zero value, and is created via implicit value
211 // initialization.
212 if (operandClass == OperandNone) {
213 opcode.numTypes--;
214 break;
215 }
216 }
217 // We should have written the terminating SPV_OPERAND_TYPE_NONE entry, but
218 // also without overflowing.
Lei Zhanga94701d2015-09-14 10:05:37 -0400219 assert((opcode.numTypes < maxNumOperands) &&
220 "Operand class list is too long. Expand "
221 "spv_opcode_desc_t.operandClass");
David Neto78c3b432015-08-27 13:03:52 -0400222 }
223 opcodeTableInitialized = true;
224}
225
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100226const char *spvGeneratorStr(uint32_t generator) {
227 switch (generator) {
228 case SPV_GENERATOR_KHRONOS:
229 return "Khronos";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100230 case SPV_GENERATOR_LUNARG:
231 return "LunarG";
David Neto1780fc42015-10-26 15:43:12 -0400232 case SPV_GENERATOR_VALVE:
233 return "Valve";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100234 case SPV_GENERATOR_CODEPLAY:
235 return "Codeplay Software Ltd.";
David Neto1780fc42015-10-26 15:43:12 -0400236 case SPV_GENERATOR_NVIDIA:
237 return "NVIDIA";
238 case SPV_GENERATOR_ARM:
239 return "ARM";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100240 default:
241 return "Unknown";
242 }
243}
244
Lei Zhangb36e7042015-10-28 13:40:52 -0400245uint32_t spvOpcodeMake(uint16_t wordCount, SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100246 return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
247}
248
Lei Zhangb36e7042015-10-28 13:40:52 -0400249void spvOpcodeSplit(const uint32_t word, uint16_t *pWordCount, SpvOp *pOpcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100250 if (pWordCount) {
251 *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
252 }
253 if (pOpcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400254 *pOpcode = (SpvOp)(0x0000ffff & word);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100255 }
256}
257
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100258spv_result_t spvOpcodeTableGet(spv_opcode_table *pInstTable) {
Lei Zhang40056702015-09-11 14:31:27 -0400259 if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100260
David Neto78c3b432015-08-27 13:03:52 -0400261 static spv_opcode_table_t table = {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100262 sizeof(opcodeTableEntries) / sizeof(spv_opcode_desc_t),
263 opcodeTableEntries};
264
David Neto78c3b432015-08-27 13:03:52 -0400265 // TODO(dneto): Consider thread safety of initialization.
266 // That is, ordering effects of the flag vs. the table updates.
Lei Zhang40056702015-09-11 14:31:27 -0400267 if (!opcodeTableInitialized) spvOpcodeTableInitialize();
David Neto78c3b432015-08-27 13:03:52 -0400268
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100269 *pInstTable = &table;
270
271 return SPV_SUCCESS;
272}
273
274spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
275 const char *name,
276 spv_opcode_desc *pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400277 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
278 if (!table) return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100279
280 // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
281 // preferable but the table requires sorting on the Opcode name, but it's
282 // static
283 // const initialized and matches the order of the spec.
284 const size_t nameLength = strlen(name);
285 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
286 if (nameLength == strlen(table->entries[opcodeIndex].name) &&
287 !strncmp(name, table->entries[opcodeIndex].name, nameLength)) {
288 // NOTE: Found out Opcode!
289 *pEntry = &table->entries[opcodeIndex];
290 return SPV_SUCCESS;
291 }
292 }
293
294 return SPV_ERROR_INVALID_LOOKUP;
295}
296
297spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
Lei Zhangb36e7042015-10-28 13:40:52 -0400298 const SpvOp opcode,
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100299 spv_opcode_desc *pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400300 if (!table) return SPV_ERROR_INVALID_TABLE;
301 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100302
303 // TODO: As above this lookup is not optimal.
304 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
305 if (opcode == table->entries[opcodeIndex].opcode) {
306 // NOTE: Found the Opcode!
307 *pEntry = &table->entries[opcodeIndex];
308 return SPV_SUCCESS;
309 }
310 }
311
312 return SPV_ERROR_INVALID_LOOKUP;
313}
314
Lei Zhangdfc50082015-08-21 11:50:55 -0400315int16_t spvOpcodeResultIdIndex(spv_opcode_desc entry) {
David Neto78c3b432015-08-27 13:03:52 -0400316 for (int16_t i = 0; i < entry->numTypes; ++i) {
Lei Zhangdfc50082015-08-21 11:50:55 -0400317 if (SPV_OPERAND_TYPE_RESULT_ID == entry->operandTypes[i]) return i;
318 }
319 return SPV_OPERAND_INVALID_RESULT_ID_INDEX;
320}
321
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100322int32_t spvOpcodeRequiresCapabilities(spv_opcode_desc entry) {
David Neto9db3a532015-10-07 16:58:38 -0400323 return entry->capabilities != 0;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100324}
325
Lei Zhangb36e7042015-10-28 13:40:52 -0400326void spvInstructionCopy(const uint32_t *words, const SpvOp opcode,
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100327 const uint16_t wordCount, const spv_endianness_t endian,
328 spv_instruction_t *pInst) {
329 pInst->opcode = opcode;
David Netob5dc8fc2015-10-06 16:22:00 -0400330 pInst->words.resize(wordCount);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100331 for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
332 pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
333 if (!wordIndex) {
334 uint16_t thisWordCount;
Lei Zhangb36e7042015-10-28 13:40:52 -0400335 SpvOp thisOpcode;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100336 spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
337 assert(opcode == thisOpcode && wordCount == thisWordCount &&
338 "Endianness failed!");
339 }
340 }
341}
342
Lei Zhangb36e7042015-10-28 13:40:52 -0400343const char *spvOpcodeString(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100344#define CASE(OPCODE) \
Lei Zhangb36e7042015-10-28 13:40:52 -0400345 case Spv##OPCODE: \
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100346 return #OPCODE;
347 switch (opcode) {
348 CASE(OpNop)
349 CASE(OpSource)
350 CASE(OpSourceExtension)
351 CASE(OpExtension)
352 CASE(OpExtInstImport)
353 CASE(OpMemoryModel)
354 CASE(OpEntryPoint)
355 CASE(OpExecutionMode)
356 CASE(OpTypeVoid)
357 CASE(OpTypeBool)
358 CASE(OpTypeInt)
359 CASE(OpTypeFloat)
360 CASE(OpTypeVector)
361 CASE(OpTypeMatrix)
362 CASE(OpTypeSampler)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100363 CASE(OpTypeArray)
364 CASE(OpTypeRuntimeArray)
365 CASE(OpTypeStruct)
366 CASE(OpTypeOpaque)
367 CASE(OpTypePointer)
368 CASE(OpTypeFunction)
369 CASE(OpTypeEvent)
370 CASE(OpTypeDeviceEvent)
371 CASE(OpTypeReserveId)
372 CASE(OpTypeQueue)
373 CASE(OpTypePipe)
374 CASE(OpConstantTrue)
375 CASE(OpConstantFalse)
376 CASE(OpConstant)
377 CASE(OpConstantComposite)
378 CASE(OpConstantSampler)
379 CASE(OpConstantNull)
380 CASE(OpSpecConstantTrue)
381 CASE(OpSpecConstantFalse)
382 CASE(OpSpecConstant)
383 CASE(OpSpecConstantComposite)
384 CASE(OpVariable)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100385 CASE(OpFunction)
386 CASE(OpFunctionParameter)
387 CASE(OpFunctionEnd)
388 CASE(OpFunctionCall)
389 CASE(OpExtInst)
390 CASE(OpUndef)
391 CASE(OpLoad)
392 CASE(OpStore)
393 CASE(OpPhi)
394 CASE(OpDecorationGroup)
395 CASE(OpDecorate)
396 CASE(OpMemberDecorate)
397 CASE(OpGroupDecorate)
398 CASE(OpGroupMemberDecorate)
399 CASE(OpName)
400 CASE(OpMemberName)
401 CASE(OpString)
402 CASE(OpLine)
403 CASE(OpVectorExtractDynamic)
404 CASE(OpVectorInsertDynamic)
405 CASE(OpVectorShuffle)
406 CASE(OpCompositeConstruct)
407 CASE(OpCompositeExtract)
408 CASE(OpCompositeInsert)
409 CASE(OpCopyObject)
410 CASE(OpCopyMemory)
411 CASE(OpCopyMemorySized)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100412 CASE(OpAccessChain)
413 CASE(OpInBoundsAccessChain)
414 CASE(OpSNegate)
415 CASE(OpFNegate)
416 CASE(OpNot)
417 CASE(OpAny)
418 CASE(OpAll)
419 CASE(OpConvertFToU)
420 CASE(OpConvertFToS)
421 CASE(OpConvertSToF)
422 CASE(OpConvertUToF)
423 CASE(OpUConvert)
424 CASE(OpSConvert)
425 CASE(OpFConvert)
426 CASE(OpConvertPtrToU)
427 CASE(OpConvertUToPtr)
428 CASE(OpPtrCastToGeneric)
429 CASE(OpGenericCastToPtr)
430 CASE(OpBitcast)
431 CASE(OpTranspose)
432 CASE(OpIsNan)
433 CASE(OpIsInf)
434 CASE(OpIsFinite)
435 CASE(OpIsNormal)
436 CASE(OpSignBitSet)
437 CASE(OpLessOrGreater)
438 CASE(OpOrdered)
439 CASE(OpUnordered)
440 CASE(OpArrayLength)
441 CASE(OpIAdd)
442 CASE(OpFAdd)
443 CASE(OpISub)
444 CASE(OpFSub)
445 CASE(OpIMul)
446 CASE(OpFMul)
447 CASE(OpUDiv)
448 CASE(OpSDiv)
449 CASE(OpFDiv)
450 CASE(OpUMod)
451 CASE(OpSRem)
452 CASE(OpSMod)
453 CASE(OpFRem)
454 CASE(OpFMod)
455 CASE(OpVectorTimesScalar)
456 CASE(OpMatrixTimesScalar)
457 CASE(OpVectorTimesMatrix)
458 CASE(OpMatrixTimesVector)
459 CASE(OpMatrixTimesMatrix)
460 CASE(OpOuterProduct)
461 CASE(OpDot)
462 CASE(OpShiftRightLogical)
463 CASE(OpShiftRightArithmetic)
464 CASE(OpShiftLeftLogical)
465 CASE(OpLogicalOr)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100466 CASE(OpLogicalAnd)
467 CASE(OpBitwiseOr)
468 CASE(OpBitwiseXor)
469 CASE(OpBitwiseAnd)
470 CASE(OpSelect)
471 CASE(OpIEqual)
472 CASE(OpFOrdEqual)
473 CASE(OpFUnordEqual)
474 CASE(OpINotEqual)
475 CASE(OpFOrdNotEqual)
476 CASE(OpFUnordNotEqual)
477 CASE(OpULessThan)
478 CASE(OpSLessThan)
479 CASE(OpFOrdLessThan)
480 CASE(OpFUnordLessThan)
481 CASE(OpUGreaterThan)
482 CASE(OpSGreaterThan)
483 CASE(OpFOrdGreaterThan)
484 CASE(OpFUnordGreaterThan)
485 CASE(OpULessThanEqual)
486 CASE(OpSLessThanEqual)
487 CASE(OpFOrdLessThanEqual)
488 CASE(OpFUnordLessThanEqual)
489 CASE(OpUGreaterThanEqual)
490 CASE(OpSGreaterThanEqual)
491 CASE(OpFOrdGreaterThanEqual)
492 CASE(OpFUnordGreaterThanEqual)
493 CASE(OpDPdx)
494 CASE(OpDPdy)
495 CASE(OpFwidth)
496 CASE(OpDPdxFine)
497 CASE(OpDPdyFine)
498 CASE(OpFwidthFine)
499 CASE(OpDPdxCoarse)
500 CASE(OpDPdyCoarse)
501 CASE(OpFwidthCoarse)
502 CASE(OpEmitVertex)
503 CASE(OpEndPrimitive)
504 CASE(OpEmitStreamVertex)
505 CASE(OpEndStreamPrimitive)
506 CASE(OpControlBarrier)
507 CASE(OpMemoryBarrier)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100508 CASE(OpAtomicLoad)
509 CASE(OpAtomicStore)
510 CASE(OpAtomicExchange)
511 CASE(OpAtomicCompareExchange)
512 CASE(OpAtomicCompareExchangeWeak)
513 CASE(OpAtomicIIncrement)
514 CASE(OpAtomicIDecrement)
515 CASE(OpAtomicIAdd)
516 CASE(OpAtomicISub)
517 CASE(OpAtomicUMin)
518 CASE(OpAtomicUMax)
519 CASE(OpAtomicAnd)
520 CASE(OpAtomicOr)
521 CASE(OpAtomicXor)
522 CASE(OpLoopMerge)
523 CASE(OpSelectionMerge)
524 CASE(OpLabel)
525 CASE(OpBranch)
526 CASE(OpBranchConditional)
527 CASE(OpSwitch)
528 CASE(OpKill)
529 CASE(OpReturn)
530 CASE(OpReturnValue)
531 CASE(OpUnreachable)
532 CASE(OpLifetimeStart)
533 CASE(OpLifetimeStop)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100534 CASE(OpAsyncGroupCopy)
535 CASE(OpWaitGroupEvents)
536 CASE(OpGroupAll)
537 CASE(OpGroupAny)
538 CASE(OpGroupBroadcast)
539 CASE(OpGroupIAdd)
540 CASE(OpGroupFAdd)
541 CASE(OpGroupFMin)
542 CASE(OpGroupUMin)
543 CASE(OpGroupSMin)
544 CASE(OpGroupFMax)
545 CASE(OpGroupUMax)
546 CASE(OpGroupSMax)
547 CASE(OpGenericCastToPtrExplicit)
548 CASE(OpGenericPtrMemSemantics)
549 CASE(OpReadPipe)
550 CASE(OpWritePipe)
551 CASE(OpReservedReadPipe)
552 CASE(OpReservedWritePipe)
553 CASE(OpReserveReadPipePackets)
554 CASE(OpReserveWritePipePackets)
555 CASE(OpCommitReadPipe)
556 CASE(OpCommitWritePipe)
557 CASE(OpIsValidReserveId)
558 CASE(OpGetNumPipePackets)
559 CASE(OpGetMaxPipePackets)
560 CASE(OpGroupReserveReadPipePackets)
561 CASE(OpGroupReserveWritePipePackets)
562 CASE(OpGroupCommitReadPipe)
563 CASE(OpGroupCommitWritePipe)
564 CASE(OpEnqueueMarker)
565 CASE(OpEnqueueKernel)
566 CASE(OpGetKernelNDrangeSubGroupCount)
567 CASE(OpGetKernelNDrangeMaxSubGroupSize)
568 CASE(OpGetKernelWorkGroupSize)
569 CASE(OpGetKernelPreferredWorkGroupSizeMultiple)
570 CASE(OpRetainEvent)
571 CASE(OpReleaseEvent)
572 CASE(OpCreateUserEvent)
573 CASE(OpIsValidEvent)
574 CASE(OpSetUserEventStatus)
575 CASE(OpCaptureEventProfilingInfo)
576 CASE(OpGetDefaultQueue)
577 CASE(OpBuildNDRange)
578 default:
579 assert(0 && "Unreachable!");
580 }
581#undef CASE
582 return "unknown";
583}
584
Lei Zhangb36e7042015-10-28 13:40:52 -0400585int32_t spvOpcodeIsType(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100586 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400587 case SpvOpTypeVoid:
588 case SpvOpTypeBool:
589 case SpvOpTypeInt:
590 case SpvOpTypeFloat:
591 case SpvOpTypeVector:
592 case SpvOpTypeMatrix:
593 case SpvOpTypeSampler:
594 case SpvOpTypeSampledImage:
595 case SpvOpTypeArray:
596 case SpvOpTypeRuntimeArray:
597 case SpvOpTypeStruct:
598 case SpvOpTypeOpaque:
599 case SpvOpTypePointer:
600 case SpvOpTypeFunction:
601 case SpvOpTypeEvent:
602 case SpvOpTypeDeviceEvent:
603 case SpvOpTypeReserveId:
604 case SpvOpTypeQueue:
605 case SpvOpTypePipe:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100606 return true;
607 default:
608 return false;
609 }
610}
611
Lei Zhangb36e7042015-10-28 13:40:52 -0400612int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100613 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400614 case SpvOpTypeInt:
615 case SpvOpTypeFloat:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100616 return true;
617 default:
618 return false;
619 }
620}
621
Lei Zhangb36e7042015-10-28 13:40:52 -0400622int32_t spvOpcodeIsConstant(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100623 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400624 case SpvOpConstantTrue:
625 case SpvOpConstantFalse:
626 case SpvOpConstant:
627 case SpvOpConstantComposite:
628 case SpvOpConstantSampler:
629 // case SpvOpConstantNull:
630 case SpvOpConstantNull:
631 case SpvOpSpecConstantTrue:
632 case SpvOpSpecConstantFalse:
633 case SpvOpSpecConstant:
634 case SpvOpSpecConstantComposite:
635 // case SpvOpSpecConstantOp:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100636 return true;
637 default:
638 return false;
639 }
640}
641
Lei Zhangb36e7042015-10-28 13:40:52 -0400642int32_t spvOpcodeIsComposite(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100643 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400644 case SpvOpTypeVector:
645 case SpvOpTypeMatrix:
646 case SpvOpTypeArray:
647 case SpvOpTypeStruct:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100648 return true;
649 default:
650 return false;
651 }
652}
653
654int32_t spvOpcodeAreTypesEqual(const spv_instruction_t *pTypeInst0,
655 const spv_instruction_t *pTypeInst1) {
Lei Zhang40056702015-09-11 14:31:27 -0400656 if (pTypeInst0->opcode != pTypeInst1->opcode) return false;
657 if (pTypeInst0->words[1] != pTypeInst1->words[1]) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100658 return true;
659}
660
Lei Zhangb36e7042015-10-28 13:40:52 -0400661int32_t spvOpcodeIsPointer(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100662 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400663 case SpvOpVariable:
664 case SpvOpAccessChain:
665 case SpvOpInBoundsAccessChain:
666 case SpvOpFunctionParameter:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100667 return true;
668 default:
669 return false;
670 }
671}
672
Lei Zhangb36e7042015-10-28 13:40:52 -0400673int32_t spvOpcodeIsObject(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100674 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400675 case SpvOpConstantTrue:
676 case SpvOpConstantFalse:
677 case SpvOpConstant:
678 case SpvOpConstantComposite:
679 // TODO: case SpvOpConstantSampler:
680 case SpvOpConstantNull:
681 case SpvOpSpecConstantTrue:
682 case SpvOpSpecConstantFalse:
683 case SpvOpSpecConstant:
684 case SpvOpSpecConstantComposite:
685 // TODO: case SpvOpSpecConstantOp:
686 case SpvOpVariable:
687 case SpvOpAccessChain:
688 case SpvOpInBoundsAccessChain:
689 case SpvOpConvertFToU:
690 case SpvOpConvertFToS:
691 case SpvOpConvertSToF:
692 case SpvOpConvertUToF:
693 case SpvOpUConvert:
694 case SpvOpSConvert:
695 case SpvOpFConvert:
696 case SpvOpConvertPtrToU:
697 // TODO: case SpvOpConvertUToPtr:
698 case SpvOpPtrCastToGeneric:
699 // TODO: case SpvOpGenericCastToPtr:
700 case SpvOpBitcast:
701 // TODO: case SpvOpGenericCastToPtrExplicit:
702 case SpvOpSatConvertSToU:
703 case SpvOpSatConvertUToS:
704 case SpvOpVectorExtractDynamic:
705 case SpvOpCompositeConstruct:
706 case SpvOpCompositeExtract:
707 case SpvOpCopyObject:
708 case SpvOpTranspose:
709 case SpvOpSNegate:
710 case SpvOpFNegate:
711 case SpvOpNot:
712 case SpvOpIAdd:
713 case SpvOpFAdd:
714 case SpvOpISub:
715 case SpvOpFSub:
716 case SpvOpIMul:
717 case SpvOpFMul:
718 case SpvOpUDiv:
719 case SpvOpSDiv:
720 case SpvOpFDiv:
721 case SpvOpUMod:
722 case SpvOpSRem:
723 case SpvOpSMod:
724 case SpvOpVectorTimesScalar:
725 case SpvOpMatrixTimesScalar:
726 case SpvOpVectorTimesMatrix:
727 case SpvOpMatrixTimesVector:
728 case SpvOpMatrixTimesMatrix:
729 case SpvOpOuterProduct:
730 case SpvOpDot:
731 case SpvOpShiftRightLogical:
732 case SpvOpShiftRightArithmetic:
733 case SpvOpShiftLeftLogical:
734 case SpvOpBitwiseOr:
735 case SpvOpBitwiseXor:
736 case SpvOpBitwiseAnd:
737 case SpvOpAny:
738 case SpvOpAll:
739 case SpvOpIsNan:
740 case SpvOpIsInf:
741 case SpvOpIsFinite:
742 case SpvOpIsNormal:
743 case SpvOpSignBitSet:
744 case SpvOpLessOrGreater:
745 case SpvOpOrdered:
746 case SpvOpUnordered:
747 case SpvOpLogicalOr:
748 case SpvOpLogicalAnd:
749 case SpvOpSelect:
750 case SpvOpIEqual:
751 case SpvOpFOrdEqual:
752 case SpvOpFUnordEqual:
753 case SpvOpINotEqual:
754 case SpvOpFOrdNotEqual:
755 case SpvOpFUnordNotEqual:
756 case SpvOpULessThan:
757 case SpvOpSLessThan:
758 case SpvOpFOrdLessThan:
759 case SpvOpFUnordLessThan:
760 case SpvOpUGreaterThan:
761 case SpvOpSGreaterThan:
762 case SpvOpFOrdGreaterThan:
763 case SpvOpFUnordGreaterThan:
764 case SpvOpULessThanEqual:
765 case SpvOpSLessThanEqual:
766 case SpvOpFOrdLessThanEqual:
767 case SpvOpFUnordLessThanEqual:
768 case SpvOpUGreaterThanEqual:
769 case SpvOpSGreaterThanEqual:
770 case SpvOpFOrdGreaterThanEqual:
771 case SpvOpFUnordGreaterThanEqual:
772 case SpvOpDPdx:
773 case SpvOpDPdy:
774 case SpvOpFwidth:
775 case SpvOpDPdxFine:
776 case SpvOpDPdyFine:
777 case SpvOpFwidthFine:
778 case SpvOpDPdxCoarse:
779 case SpvOpDPdyCoarse:
780 case SpvOpFwidthCoarse:
781 case SpvOpReturnValue:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100782 return true;
783 default:
784 return false;
785 }
786}
787
Lei Zhangb36e7042015-10-28 13:40:52 -0400788int32_t spvOpcodeIsBasicTypeNullable(SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100789 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400790 case SpvOpTypeBool:
791 case SpvOpTypeInt:
792 case SpvOpTypeFloat:
793 case SpvOpTypePointer:
794 case SpvOpTypeEvent:
795 case SpvOpTypeDeviceEvent:
796 case SpvOpTypeReserveId:
797 case SpvOpTypeQueue:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100798 return true;
799 default:
800 return false;
801 }
802}
803
804int32_t spvInstructionIsInBasicBlock(const spv_instruction_t *pFirstInst,
805 const spv_instruction_t *pInst) {
806 while (pFirstInst != pInst) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400807 if (SpvOpFunction == pInst->opcode) break;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100808 pInst--;
809 }
Lei Zhangb36e7042015-10-28 13:40:52 -0400810 if (SpvOpFunction != pInst->opcode) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100811 return true;
812}
813
Lei Zhangb36e7042015-10-28 13:40:52 -0400814int32_t spvOpcodeIsValue(SpvOp opcode) {
Lei Zhang40056702015-09-11 14:31:27 -0400815 if (spvOpcodeIsPointer(opcode)) return true;
816 if (spvOpcodeIsConstant(opcode)) return true;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100817 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400818 case SpvOpLoad:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100819 // TODO: Other Opcode's resulting in a value
820 return true;
821 default:
822 return false;
823 }
824}
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400825
Lei Zhangb36e7042015-10-28 13:40:52 -0400826int32_t spvOpcodeGeneratesType(SpvOp op) {
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400827 switch(op) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400828 case SpvOpTypeVoid:
829 case SpvOpTypeBool:
830 case SpvOpTypeInt:
831 case SpvOpTypeFloat:
832 case SpvOpTypeVector:
833 case SpvOpTypeMatrix:
834 case SpvOpTypeImage:
835 case SpvOpTypeSampler:
836 case SpvOpTypeSampledImage:
837 case SpvOpTypeArray:
838 case SpvOpTypeRuntimeArray:
839 case SpvOpTypeStruct:
840 case SpvOpTypeOpaque:
841 case SpvOpTypePointer:
842 case SpvOpTypeFunction:
843 case SpvOpTypeEvent:
844 case SpvOpTypeDeviceEvent:
845 case SpvOpTypeReserveId:
846 case SpvOpTypeQueue:
847 case SpvOpTypePipe:
848 case SpvOpTypeForwardPointer:
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400849 return true;
850 default:;
851 }
852 return 0;
853}