blob: 60f1ceb636ef1df8495dc0d790fce3862eae28d4 [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[] = {
Lei Zhang1a0334e2015-11-02 09:41:20 -050047#define EmptyList \
48 {}
49#define List(...) \
50 { __VA_ARGS__ }
Lei Zhangb36e7042015-10-28 13:40:52 -040051#define Capability(X) SPV_CAPABILITY_AS_MASK(SpvCapability##X)
Lei Zhang1a0334e2015-11-02 09:41:20 -050052#define Capability2(X, Y) Capability(X) | Capability(Y)
53#define SpvCapabilityNone \
54 0 // Needed so Capability(None) still expands to valid syntax.
55#define Instruction(Name, HasResult, HasType, NumLogicalOperands, \
56 NumCapabilities, CapabilityRequired, IsVariable, \
57 LogicalArgsList) \
58 { \
59 #Name, SpvOp##Name, \
60 (NumCapabilities) ? (CapabilityRequired) : 0, 0, \
61 {}, /* Filled in later. Operand list, including \
62 result id and type id, if needed */ \
63 HasResult, HasType, LogicalArgsList \
64 } \
65 ,
David Neto78c3b432015-08-27 13:03:52 -040066#include "opcode.inc"
67#undef EmptyList
68#undef List
69#undef Capability
Dejan Mircevski205408b2015-09-30 16:42:34 -040070#undef Capability2
David Neto78c3b432015-08-27 13:03:52 -040071#undef CapabilityNone
72#undef Instruction
73};
74
75// Has the opcodeTableEntries table been fully elaborated?
76// That is, are the operandTypes fields initialized?
77bool opcodeTableInitialized = false;
78
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010079// Opcode API
80
David Neto78c3b432015-08-27 13:03:52 -040081// Converts the given operand class enum (from the SPIR-V document generation
82// logic) to the operand type required by the parser.
83// This only applies to logical operands.
Lei Zhangb36e7042015-10-28 13:40:52 -040084spv_operand_type_t convertOperandClassToType(SpvOp opcode,
85 OperandClass operandClass) {
David Neto78c3b432015-08-27 13:03:52 -040086 // The spec document generator uses OptionalOperandLiteral for several kinds
87 // of repeating values. Our parser needs more specific information about
88 // what is being repeated.
89 if (operandClass == OperandOptionalLiteral) {
Lei Zhang40056702015-09-11 14:31:27 -040090 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -040091 case SpvOpLoad:
92 case SpvOpStore:
93 case SpvOpCopyMemory:
94 case SpvOpCopyMemorySized:
David Neto3fca4cd2015-09-17 17:39:45 -040095 // Expect an optional mask. When the Aligned bit is set in the mask,
96 // we will later add the expectation of a literal number operand.
97 return SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS;
Lei Zhangb36e7042015-10-28 13:40:52 -040098 case SpvOpExecutionMode:
David Neto78c3b432015-08-27 13:03:52 -040099 return SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE;
100 default:
101 break;
102 }
Lei Zhangb41d1502015-09-14 15:22:23 -0400103 } else if (operandClass == OperandVariableLiterals) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400104 if (opcode == SpvOpConstant || opcode == SpvOpSpecConstant)
Lei Zhangb41d1502015-09-14 15:22:23 -0400105 return SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER;
David Neto78c3b432015-08-27 13:03:52 -0400106 }
107
Lei Zhang1a0334e2015-11-02 09:41:20 -0500108 switch (operandClass) {
109 case OperandNone:
110 return SPV_OPERAND_TYPE_NONE;
111 case OperandId:
112 return SPV_OPERAND_TYPE_ID;
113 case OperandOptionalId:
114 return SPV_OPERAND_TYPE_OPTIONAL_ID;
115 case OperandOptionalImage:
116 return SPV_OPERAND_TYPE_OPTIONAL_IMAGE;
117 case OperandVariableIds:
118 return SPV_OPERAND_TYPE_VARIABLE_ID;
David Neto561dc4e2015-09-25 14:23:29 -0400119 // The spec only uses OptionalLiteral for an optional literal number.
Lei Zhang1a0334e2015-11-02 09:41:20 -0500120 case OperandOptionalLiteral:
121 return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER;
122 case OperandOptionalLiteralString:
123 return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING;
David Neto561dc4e2015-09-25 14:23:29 -0400124 // This is only used for sequences of literal numbers.
Lei Zhang1a0334e2015-11-02 09:41:20 -0500125 case OperandVariableLiterals:
126 return SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER;
David Neto445ce442015-10-15 15:22:06 -0400127 case OperandLiteralNumber:
Lei Zhangb36e7042015-10-28 13:40:52 -0400128 if (opcode == SpvOpExtInst) {
David Neto445ce442015-10-15 15:22:06 -0400129 // We use a special operand type for the extension instruction number.
Lei Zhang1a0334e2015-11-02 09:41:20 -0500130 // For now, we assume there is only one LiteraNumber argument to
131 // OpExtInst, and it is the extension instruction argument.
David Neto445ce442015-10-15 15:22:06 -0400132 // See the ExtInst entry in opcode.inc
133 // TODO(dneto): Use a function to confirm the assumption, and to verify
134 // that the index into the operandClass is 1, as expected.
135 return SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER;
136 }
137 return SPV_OPERAND_TYPE_LITERAL_INTEGER;
Lei Zhang1a0334e2015-11-02 09:41:20 -0500138 case OperandLiteralString:
139 return SPV_OPERAND_TYPE_LITERAL_STRING;
140 case OperandSource:
141 return SPV_OPERAND_TYPE_SOURCE_LANGUAGE;
142 case OperandExecutionModel:
143 return SPV_OPERAND_TYPE_EXECUTION_MODEL;
144 case OperandAddressing:
145 return SPV_OPERAND_TYPE_ADDRESSING_MODEL;
146 case OperandMemory:
147 return SPV_OPERAND_TYPE_MEMORY_MODEL;
148 case OperandExecutionMode:
149 return SPV_OPERAND_TYPE_EXECUTION_MODE;
150 case OperandStorage:
151 return SPV_OPERAND_TYPE_STORAGE_CLASS;
152 case OperandDimensionality:
153 return SPV_OPERAND_TYPE_DIMENSIONALITY;
154 case OperandSamplerAddressingMode:
155 return SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE;
156 case OperandSamplerFilterMode:
157 return SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE;
158 case OperandSamplerImageFormat:
159 return SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT;
David Neto7cefb232015-09-28 15:33:49 -0400160 case OperandImageChannelOrder:
161 // This is only used to describe the value generated by OpImageQueryOrder.
162 // It is not used as an operand.
163 break;
164 case OperandImageChannelDataType:
Lei Zhang1a0334e2015-11-02 09:41:20 -0500165 // This is only used to describe the value generated by
166 // OpImageQueryFormat. It is not used as an operand.
David Neto7cefb232015-09-28 15:33:49 -0400167 break;
168 case OperandImageOperands:
Dejan Mircevskif8e091a2015-10-13 14:41:31 -0400169 // This is not used in opcode.inc. It only exists to generate the
170 // corresponding spec section. In parsing, image operands meld into the
171 // OperandOptionalImage case.
David Neto7cefb232015-09-28 15:33:49 -0400172 break;
Lei Zhang1a0334e2015-11-02 09:41:20 -0500173 case OperandFPFastMath:
174 return SPV_OPERAND_TYPE_FP_FAST_MATH_MODE;
175 case OperandFPRoundingMode:
176 return SPV_OPERAND_TYPE_FP_ROUNDING_MODE;
177 case OperandLinkageType:
178 return SPV_OPERAND_TYPE_LINKAGE_TYPE;
179 case OperandAccessQualifier:
180 return SPV_OPERAND_TYPE_ACCESS_QUALIFIER;
181 case OperandFuncParamAttr:
182 return SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE;
183 case OperandDecoration:
184 return SPV_OPERAND_TYPE_DECORATION;
185 case OperandBuiltIn:
186 return SPV_OPERAND_TYPE_BUILT_IN;
187 case OperandSelect:
188 return SPV_OPERAND_TYPE_SELECTION_CONTROL;
189 case OperandLoop:
190 return SPV_OPERAND_TYPE_LOOP_CONTROL;
191 case OperandFunction:
192 return SPV_OPERAND_TYPE_FUNCTION_CONTROL;
193 case OperandMemorySemantics:
194 return SPV_OPERAND_TYPE_MEMORY_SEMANTICS;
David Neto78c3b432015-08-27 13:03:52 -0400195 case OperandMemoryAccess:
David Neto7cefb232015-09-28 15:33:49 -0400196 // This case does not occur in the table for SPIR-V 0.99 Rev 32.
David Neto3fca4cd2015-09-17 17:39:45 -0400197 // We expect that it will become SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
David Neto78c3b432015-08-27 13:03:52 -0400198 // and we can remove the special casing above for memory operation
199 // instructions.
200 break;
Lei Zhang1a0334e2015-11-02 09:41:20 -0500201 case OperandScope:
202 return SPV_OPERAND_TYPE_EXECUTION_SCOPE;
203 case OperandGroupOperation:
204 return SPV_OPERAND_TYPE_GROUP_OPERATION;
205 case OperandKernelEnqueueFlags:
206 return SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS;
207 case OperandKernelProfilingInfo:
208 return SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO;
209 case OperandCapability:
210 return SPV_OPERAND_TYPE_CAPABILITY;
David Neto78c3b432015-08-27 13:03:52 -0400211
212 // Used by GroupMemberDecorate
Lei Zhang1a0334e2015-11-02 09:41:20 -0500213 case OperandVariableIdLiteral:
214 return SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER;
David Neto78c3b432015-08-27 13:03:52 -0400215
216 // Used by Switch
Lei Zhang1a0334e2015-11-02 09:41:20 -0500217 case OperandVariableLiteralId:
218 return SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID;
David Neto78c3b432015-08-27 13:03:52 -0400219
220 // These exceptional cases shouldn't occur.
221 case OperandCount:
222 default:
223 break;
224 }
225 assert(0 && "Unexpected operand class");
226 return SPV_OPERAND_TYPE_NONE;
227}
228
Lei Zhanga94701d2015-09-14 10:05:37 -0400229} // anonymous namespace
David Neto78c3b432015-08-27 13:03:52 -0400230
231// Finish populating the opcodeTableEntries array.
232void spvOpcodeTableInitialize() {
233 // Compute the operandTypes field for each entry.
Lei Zhang1a0334e2015-11-02 09:41:20 -0500234 for (auto& opcode : opcodeTableEntries) {
David Neto78c3b432015-08-27 13:03:52 -0400235 opcode.numTypes = 0;
236 // Type ID always comes first, if present.
237 if (opcode.hasType)
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400238 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_TYPE_ID;
David Neto78c3b432015-08-27 13:03:52 -0400239 // Result ID always comes next, if present
240 if (opcode.hasResult)
241 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_RESULT_ID;
Lei Zhanga94701d2015-09-14 10:05:37 -0400242 const uint16_t maxNumOperands =
243 sizeof(opcode.operandTypes) / sizeof(opcode.operandTypes[0]);
244 const uint16_t maxNumClasses =
245 sizeof(opcode.operandClass) / sizeof(opcode.operandClass[0]);
246 for (uint16_t classIndex = 0;
247 opcode.numTypes < maxNumOperands && classIndex < maxNumClasses;
248 classIndex++) {
David Neto78c3b432015-08-27 13:03:52 -0400249 const OperandClass operandClass = opcode.operandClass[classIndex];
Lei Zhanga94701d2015-09-14 10:05:37 -0400250 opcode.operandTypes[opcode.numTypes++] =
251 convertOperandClassToType(opcode.opcode, operandClass);
David Neto78c3b432015-08-27 13:03:52 -0400252 // The OperandNone value is not explicitly represented in the .inc file.
253 // However, it is the zero value, and is created via implicit value
254 // initialization.
255 if (operandClass == OperandNone) {
256 opcode.numTypes--;
257 break;
258 }
259 }
260 // We should have written the terminating SPV_OPERAND_TYPE_NONE entry, but
261 // also without overflowing.
Lei Zhanga94701d2015-09-14 10:05:37 -0400262 assert((opcode.numTypes < maxNumOperands) &&
263 "Operand class list is too long. Expand "
264 "spv_opcode_desc_t.operandClass");
David Neto78c3b432015-08-27 13:03:52 -0400265 }
266 opcodeTableInitialized = true;
267}
268
Lei Zhang1a0334e2015-11-02 09:41:20 -0500269const char* spvGeneratorStr(uint32_t generator) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100270 switch (generator) {
271 case SPV_GENERATOR_KHRONOS:
272 return "Khronos";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100273 case SPV_GENERATOR_LUNARG:
274 return "LunarG";
David Neto1780fc42015-10-26 15:43:12 -0400275 case SPV_GENERATOR_VALVE:
276 return "Valve";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100277 case SPV_GENERATOR_CODEPLAY:
278 return "Codeplay Software Ltd.";
David Neto1780fc42015-10-26 15:43:12 -0400279 case SPV_GENERATOR_NVIDIA:
280 return "NVIDIA";
281 case SPV_GENERATOR_ARM:
282 return "ARM";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100283 default:
284 return "Unknown";
285 }
286}
287
Lei Zhangb36e7042015-10-28 13:40:52 -0400288uint32_t spvOpcodeMake(uint16_t wordCount, SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100289 return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
290}
291
Lei Zhang1a0334e2015-11-02 09:41:20 -0500292void spvOpcodeSplit(const uint32_t word, uint16_t* pWordCount, SpvOp* pOpcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100293 if (pWordCount) {
294 *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
295 }
296 if (pOpcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400297 *pOpcode = (SpvOp)(0x0000ffff & word);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100298 }
299}
300
Lei Zhang1a0334e2015-11-02 09:41:20 -0500301spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable) {
Lei Zhang40056702015-09-11 14:31:27 -0400302 if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100303
David Neto78c3b432015-08-27 13:03:52 -0400304 static spv_opcode_table_t table = {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100305 sizeof(opcodeTableEntries) / sizeof(spv_opcode_desc_t),
306 opcodeTableEntries};
307
David Neto78c3b432015-08-27 13:03:52 -0400308 // TODO(dneto): Consider thread safety of initialization.
309 // That is, ordering effects of the flag vs. the table updates.
Lei Zhang40056702015-09-11 14:31:27 -0400310 if (!opcodeTableInitialized) spvOpcodeTableInitialize();
David Neto78c3b432015-08-27 13:03:52 -0400311
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100312 *pInstTable = &table;
313
314 return SPV_SUCCESS;
315}
316
317spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500318 const char* name,
319 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400320 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
321 if (!table) return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100322
323 // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
324 // preferable but the table requires sorting on the Opcode name, but it's
325 // static
326 // const initialized and matches the order of the spec.
327 const size_t nameLength = strlen(name);
328 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
329 if (nameLength == strlen(table->entries[opcodeIndex].name) &&
330 !strncmp(name, table->entries[opcodeIndex].name, nameLength)) {
331 // NOTE: Found out Opcode!
332 *pEntry = &table->entries[opcodeIndex];
333 return SPV_SUCCESS;
334 }
335 }
336
337 return SPV_ERROR_INVALID_LOOKUP;
338}
339
340spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
Lei Zhangb36e7042015-10-28 13:40:52 -0400341 const SpvOp opcode,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500342 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400343 if (!table) return SPV_ERROR_INVALID_TABLE;
344 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100345
346 // TODO: As above this lookup is not optimal.
347 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
348 if (opcode == table->entries[opcodeIndex].opcode) {
349 // NOTE: Found the Opcode!
350 *pEntry = &table->entries[opcodeIndex];
351 return SPV_SUCCESS;
352 }
353 }
354
355 return SPV_ERROR_INVALID_LOOKUP;
356}
357
Lei Zhangdfc50082015-08-21 11:50:55 -0400358int16_t spvOpcodeResultIdIndex(spv_opcode_desc entry) {
David Neto78c3b432015-08-27 13:03:52 -0400359 for (int16_t i = 0; i < entry->numTypes; ++i) {
Lei Zhangdfc50082015-08-21 11:50:55 -0400360 if (SPV_OPERAND_TYPE_RESULT_ID == entry->operandTypes[i]) return i;
361 }
362 return SPV_OPERAND_INVALID_RESULT_ID_INDEX;
363}
364
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100365int32_t spvOpcodeRequiresCapabilities(spv_opcode_desc entry) {
David Neto9db3a532015-10-07 16:58:38 -0400366 return entry->capabilities != 0;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100367}
368
Lei Zhang1a0334e2015-11-02 09:41:20 -0500369void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100370 const uint16_t wordCount, const spv_endianness_t endian,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500371 spv_instruction_t* pInst) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100372 pInst->opcode = opcode;
David Netob5dc8fc2015-10-06 16:22:00 -0400373 pInst->words.resize(wordCount);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100374 for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
375 pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
376 if (!wordIndex) {
377 uint16_t thisWordCount;
Lei Zhangb36e7042015-10-28 13:40:52 -0400378 SpvOp thisOpcode;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100379 spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
380 assert(opcode == thisOpcode && wordCount == thisWordCount &&
381 "Endianness failed!");
382 }
383 }
384}
385
Lei Zhang1a0334e2015-11-02 09:41:20 -0500386const char* spvOpcodeString(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100387#define CASE(OPCODE) \
Lei Zhang1a0334e2015-11-02 09:41:20 -0500388 case Spv##OPCODE: \
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100389 return #OPCODE;
390 switch (opcode) {
391 CASE(OpNop)
392 CASE(OpSource)
393 CASE(OpSourceExtension)
394 CASE(OpExtension)
395 CASE(OpExtInstImport)
396 CASE(OpMemoryModel)
397 CASE(OpEntryPoint)
398 CASE(OpExecutionMode)
399 CASE(OpTypeVoid)
400 CASE(OpTypeBool)
401 CASE(OpTypeInt)
402 CASE(OpTypeFloat)
403 CASE(OpTypeVector)
404 CASE(OpTypeMatrix)
405 CASE(OpTypeSampler)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100406 CASE(OpTypeArray)
407 CASE(OpTypeRuntimeArray)
408 CASE(OpTypeStruct)
409 CASE(OpTypeOpaque)
410 CASE(OpTypePointer)
411 CASE(OpTypeFunction)
412 CASE(OpTypeEvent)
413 CASE(OpTypeDeviceEvent)
414 CASE(OpTypeReserveId)
415 CASE(OpTypeQueue)
416 CASE(OpTypePipe)
417 CASE(OpConstantTrue)
418 CASE(OpConstantFalse)
419 CASE(OpConstant)
420 CASE(OpConstantComposite)
421 CASE(OpConstantSampler)
422 CASE(OpConstantNull)
423 CASE(OpSpecConstantTrue)
424 CASE(OpSpecConstantFalse)
425 CASE(OpSpecConstant)
426 CASE(OpSpecConstantComposite)
427 CASE(OpVariable)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100428 CASE(OpFunction)
429 CASE(OpFunctionParameter)
430 CASE(OpFunctionEnd)
431 CASE(OpFunctionCall)
432 CASE(OpExtInst)
433 CASE(OpUndef)
434 CASE(OpLoad)
435 CASE(OpStore)
436 CASE(OpPhi)
437 CASE(OpDecorationGroup)
438 CASE(OpDecorate)
439 CASE(OpMemberDecorate)
440 CASE(OpGroupDecorate)
441 CASE(OpGroupMemberDecorate)
442 CASE(OpName)
443 CASE(OpMemberName)
444 CASE(OpString)
445 CASE(OpLine)
446 CASE(OpVectorExtractDynamic)
447 CASE(OpVectorInsertDynamic)
448 CASE(OpVectorShuffle)
449 CASE(OpCompositeConstruct)
450 CASE(OpCompositeExtract)
451 CASE(OpCompositeInsert)
452 CASE(OpCopyObject)
453 CASE(OpCopyMemory)
454 CASE(OpCopyMemorySized)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100455 CASE(OpAccessChain)
456 CASE(OpInBoundsAccessChain)
457 CASE(OpSNegate)
458 CASE(OpFNegate)
459 CASE(OpNot)
460 CASE(OpAny)
461 CASE(OpAll)
462 CASE(OpConvertFToU)
463 CASE(OpConvertFToS)
464 CASE(OpConvertSToF)
465 CASE(OpConvertUToF)
466 CASE(OpUConvert)
467 CASE(OpSConvert)
468 CASE(OpFConvert)
469 CASE(OpConvertPtrToU)
470 CASE(OpConvertUToPtr)
471 CASE(OpPtrCastToGeneric)
472 CASE(OpGenericCastToPtr)
473 CASE(OpBitcast)
474 CASE(OpTranspose)
475 CASE(OpIsNan)
476 CASE(OpIsInf)
477 CASE(OpIsFinite)
478 CASE(OpIsNormal)
479 CASE(OpSignBitSet)
480 CASE(OpLessOrGreater)
481 CASE(OpOrdered)
482 CASE(OpUnordered)
483 CASE(OpArrayLength)
484 CASE(OpIAdd)
485 CASE(OpFAdd)
486 CASE(OpISub)
487 CASE(OpFSub)
488 CASE(OpIMul)
489 CASE(OpFMul)
490 CASE(OpUDiv)
491 CASE(OpSDiv)
492 CASE(OpFDiv)
493 CASE(OpUMod)
494 CASE(OpSRem)
495 CASE(OpSMod)
496 CASE(OpFRem)
497 CASE(OpFMod)
498 CASE(OpVectorTimesScalar)
499 CASE(OpMatrixTimesScalar)
500 CASE(OpVectorTimesMatrix)
501 CASE(OpMatrixTimesVector)
502 CASE(OpMatrixTimesMatrix)
503 CASE(OpOuterProduct)
504 CASE(OpDot)
505 CASE(OpShiftRightLogical)
506 CASE(OpShiftRightArithmetic)
507 CASE(OpShiftLeftLogical)
508 CASE(OpLogicalOr)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100509 CASE(OpLogicalAnd)
510 CASE(OpBitwiseOr)
511 CASE(OpBitwiseXor)
512 CASE(OpBitwiseAnd)
513 CASE(OpSelect)
514 CASE(OpIEqual)
515 CASE(OpFOrdEqual)
516 CASE(OpFUnordEqual)
517 CASE(OpINotEqual)
518 CASE(OpFOrdNotEqual)
519 CASE(OpFUnordNotEqual)
520 CASE(OpULessThan)
521 CASE(OpSLessThan)
522 CASE(OpFOrdLessThan)
523 CASE(OpFUnordLessThan)
524 CASE(OpUGreaterThan)
525 CASE(OpSGreaterThan)
526 CASE(OpFOrdGreaterThan)
527 CASE(OpFUnordGreaterThan)
528 CASE(OpULessThanEqual)
529 CASE(OpSLessThanEqual)
530 CASE(OpFOrdLessThanEqual)
531 CASE(OpFUnordLessThanEqual)
532 CASE(OpUGreaterThanEqual)
533 CASE(OpSGreaterThanEqual)
534 CASE(OpFOrdGreaterThanEqual)
535 CASE(OpFUnordGreaterThanEqual)
536 CASE(OpDPdx)
537 CASE(OpDPdy)
538 CASE(OpFwidth)
539 CASE(OpDPdxFine)
540 CASE(OpDPdyFine)
541 CASE(OpFwidthFine)
542 CASE(OpDPdxCoarse)
543 CASE(OpDPdyCoarse)
544 CASE(OpFwidthCoarse)
545 CASE(OpEmitVertex)
546 CASE(OpEndPrimitive)
547 CASE(OpEmitStreamVertex)
548 CASE(OpEndStreamPrimitive)
549 CASE(OpControlBarrier)
550 CASE(OpMemoryBarrier)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100551 CASE(OpAtomicLoad)
552 CASE(OpAtomicStore)
553 CASE(OpAtomicExchange)
554 CASE(OpAtomicCompareExchange)
555 CASE(OpAtomicCompareExchangeWeak)
556 CASE(OpAtomicIIncrement)
557 CASE(OpAtomicIDecrement)
558 CASE(OpAtomicIAdd)
559 CASE(OpAtomicISub)
560 CASE(OpAtomicUMin)
561 CASE(OpAtomicUMax)
562 CASE(OpAtomicAnd)
563 CASE(OpAtomicOr)
564 CASE(OpAtomicXor)
565 CASE(OpLoopMerge)
566 CASE(OpSelectionMerge)
567 CASE(OpLabel)
568 CASE(OpBranch)
569 CASE(OpBranchConditional)
570 CASE(OpSwitch)
571 CASE(OpKill)
572 CASE(OpReturn)
573 CASE(OpReturnValue)
574 CASE(OpUnreachable)
575 CASE(OpLifetimeStart)
576 CASE(OpLifetimeStop)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100577 CASE(OpAsyncGroupCopy)
578 CASE(OpWaitGroupEvents)
579 CASE(OpGroupAll)
580 CASE(OpGroupAny)
581 CASE(OpGroupBroadcast)
582 CASE(OpGroupIAdd)
583 CASE(OpGroupFAdd)
584 CASE(OpGroupFMin)
585 CASE(OpGroupUMin)
586 CASE(OpGroupSMin)
587 CASE(OpGroupFMax)
588 CASE(OpGroupUMax)
589 CASE(OpGroupSMax)
590 CASE(OpGenericCastToPtrExplicit)
591 CASE(OpGenericPtrMemSemantics)
592 CASE(OpReadPipe)
593 CASE(OpWritePipe)
594 CASE(OpReservedReadPipe)
595 CASE(OpReservedWritePipe)
596 CASE(OpReserveReadPipePackets)
597 CASE(OpReserveWritePipePackets)
598 CASE(OpCommitReadPipe)
599 CASE(OpCommitWritePipe)
600 CASE(OpIsValidReserveId)
601 CASE(OpGetNumPipePackets)
602 CASE(OpGetMaxPipePackets)
603 CASE(OpGroupReserveReadPipePackets)
604 CASE(OpGroupReserveWritePipePackets)
605 CASE(OpGroupCommitReadPipe)
606 CASE(OpGroupCommitWritePipe)
607 CASE(OpEnqueueMarker)
608 CASE(OpEnqueueKernel)
609 CASE(OpGetKernelNDrangeSubGroupCount)
610 CASE(OpGetKernelNDrangeMaxSubGroupSize)
611 CASE(OpGetKernelWorkGroupSize)
612 CASE(OpGetKernelPreferredWorkGroupSizeMultiple)
613 CASE(OpRetainEvent)
614 CASE(OpReleaseEvent)
615 CASE(OpCreateUserEvent)
616 CASE(OpIsValidEvent)
617 CASE(OpSetUserEventStatus)
618 CASE(OpCaptureEventProfilingInfo)
619 CASE(OpGetDefaultQueue)
620 CASE(OpBuildNDRange)
621 default:
622 assert(0 && "Unreachable!");
623 }
624#undef CASE
625 return "unknown";
626}
627
Lei Zhangb36e7042015-10-28 13:40:52 -0400628int32_t spvOpcodeIsType(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100629 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400630 case SpvOpTypeVoid:
631 case SpvOpTypeBool:
632 case SpvOpTypeInt:
633 case SpvOpTypeFloat:
634 case SpvOpTypeVector:
635 case SpvOpTypeMatrix:
636 case SpvOpTypeSampler:
637 case SpvOpTypeSampledImage:
638 case SpvOpTypeArray:
639 case SpvOpTypeRuntimeArray:
640 case SpvOpTypeStruct:
641 case SpvOpTypeOpaque:
642 case SpvOpTypePointer:
643 case SpvOpTypeFunction:
644 case SpvOpTypeEvent:
645 case SpvOpTypeDeviceEvent:
646 case SpvOpTypeReserveId:
647 case SpvOpTypeQueue:
648 case SpvOpTypePipe:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100649 return true;
650 default:
651 return false;
652 }
653}
654
Lei Zhangb36e7042015-10-28 13:40:52 -0400655int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100656 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400657 case SpvOpTypeInt:
658 case SpvOpTypeFloat:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100659 return true;
660 default:
661 return false;
662 }
663}
664
Lei Zhangb36e7042015-10-28 13:40:52 -0400665int32_t spvOpcodeIsConstant(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100666 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400667 case SpvOpConstantTrue:
668 case SpvOpConstantFalse:
669 case SpvOpConstant:
670 case SpvOpConstantComposite:
671 case SpvOpConstantSampler:
672 // case SpvOpConstantNull:
673 case SpvOpConstantNull:
674 case SpvOpSpecConstantTrue:
675 case SpvOpSpecConstantFalse:
676 case SpvOpSpecConstant:
677 case SpvOpSpecConstantComposite:
678 // case SpvOpSpecConstantOp:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100679 return true;
680 default:
681 return false;
682 }
683}
684
Lei Zhangb36e7042015-10-28 13:40:52 -0400685int32_t spvOpcodeIsComposite(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100686 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400687 case SpvOpTypeVector:
688 case SpvOpTypeMatrix:
689 case SpvOpTypeArray:
690 case SpvOpTypeStruct:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100691 return true;
692 default:
693 return false;
694 }
695}
696
Lei Zhang1a0334e2015-11-02 09:41:20 -0500697int32_t spvOpcodeAreTypesEqual(const spv_instruction_t* pTypeInst0,
698 const spv_instruction_t* pTypeInst1) {
Lei Zhang40056702015-09-11 14:31:27 -0400699 if (pTypeInst0->opcode != pTypeInst1->opcode) return false;
700 if (pTypeInst0->words[1] != pTypeInst1->words[1]) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100701 return true;
702}
703
Lei Zhangb36e7042015-10-28 13:40:52 -0400704int32_t spvOpcodeIsPointer(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100705 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400706 case SpvOpVariable:
707 case SpvOpAccessChain:
708 case SpvOpInBoundsAccessChain:
709 case SpvOpFunctionParameter:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100710 return true;
711 default:
712 return false;
713 }
714}
715
Lei Zhangb36e7042015-10-28 13:40:52 -0400716int32_t spvOpcodeIsObject(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100717 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400718 case SpvOpConstantTrue:
719 case SpvOpConstantFalse:
720 case SpvOpConstant:
721 case SpvOpConstantComposite:
722 // TODO: case SpvOpConstantSampler:
723 case SpvOpConstantNull:
724 case SpvOpSpecConstantTrue:
725 case SpvOpSpecConstantFalse:
726 case SpvOpSpecConstant:
727 case SpvOpSpecConstantComposite:
728 // TODO: case SpvOpSpecConstantOp:
729 case SpvOpVariable:
730 case SpvOpAccessChain:
731 case SpvOpInBoundsAccessChain:
732 case SpvOpConvertFToU:
733 case SpvOpConvertFToS:
734 case SpvOpConvertSToF:
735 case SpvOpConvertUToF:
736 case SpvOpUConvert:
737 case SpvOpSConvert:
738 case SpvOpFConvert:
739 case SpvOpConvertPtrToU:
740 // TODO: case SpvOpConvertUToPtr:
741 case SpvOpPtrCastToGeneric:
742 // TODO: case SpvOpGenericCastToPtr:
743 case SpvOpBitcast:
744 // TODO: case SpvOpGenericCastToPtrExplicit:
745 case SpvOpSatConvertSToU:
746 case SpvOpSatConvertUToS:
747 case SpvOpVectorExtractDynamic:
748 case SpvOpCompositeConstruct:
749 case SpvOpCompositeExtract:
750 case SpvOpCopyObject:
751 case SpvOpTranspose:
752 case SpvOpSNegate:
753 case SpvOpFNegate:
754 case SpvOpNot:
755 case SpvOpIAdd:
756 case SpvOpFAdd:
757 case SpvOpISub:
758 case SpvOpFSub:
759 case SpvOpIMul:
760 case SpvOpFMul:
761 case SpvOpUDiv:
762 case SpvOpSDiv:
763 case SpvOpFDiv:
764 case SpvOpUMod:
765 case SpvOpSRem:
766 case SpvOpSMod:
767 case SpvOpVectorTimesScalar:
768 case SpvOpMatrixTimesScalar:
769 case SpvOpVectorTimesMatrix:
770 case SpvOpMatrixTimesVector:
771 case SpvOpMatrixTimesMatrix:
772 case SpvOpOuterProduct:
773 case SpvOpDot:
774 case SpvOpShiftRightLogical:
775 case SpvOpShiftRightArithmetic:
776 case SpvOpShiftLeftLogical:
777 case SpvOpBitwiseOr:
778 case SpvOpBitwiseXor:
779 case SpvOpBitwiseAnd:
780 case SpvOpAny:
781 case SpvOpAll:
782 case SpvOpIsNan:
783 case SpvOpIsInf:
784 case SpvOpIsFinite:
785 case SpvOpIsNormal:
786 case SpvOpSignBitSet:
787 case SpvOpLessOrGreater:
788 case SpvOpOrdered:
789 case SpvOpUnordered:
790 case SpvOpLogicalOr:
791 case SpvOpLogicalAnd:
792 case SpvOpSelect:
793 case SpvOpIEqual:
794 case SpvOpFOrdEqual:
795 case SpvOpFUnordEqual:
796 case SpvOpINotEqual:
797 case SpvOpFOrdNotEqual:
798 case SpvOpFUnordNotEqual:
799 case SpvOpULessThan:
800 case SpvOpSLessThan:
801 case SpvOpFOrdLessThan:
802 case SpvOpFUnordLessThan:
803 case SpvOpUGreaterThan:
804 case SpvOpSGreaterThan:
805 case SpvOpFOrdGreaterThan:
806 case SpvOpFUnordGreaterThan:
807 case SpvOpULessThanEqual:
808 case SpvOpSLessThanEqual:
809 case SpvOpFOrdLessThanEqual:
810 case SpvOpFUnordLessThanEqual:
811 case SpvOpUGreaterThanEqual:
812 case SpvOpSGreaterThanEqual:
813 case SpvOpFOrdGreaterThanEqual:
814 case SpvOpFUnordGreaterThanEqual:
815 case SpvOpDPdx:
816 case SpvOpDPdy:
817 case SpvOpFwidth:
818 case SpvOpDPdxFine:
819 case SpvOpDPdyFine:
820 case SpvOpFwidthFine:
821 case SpvOpDPdxCoarse:
822 case SpvOpDPdyCoarse:
823 case SpvOpFwidthCoarse:
824 case SpvOpReturnValue:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100825 return true;
826 default:
827 return false;
828 }
829}
830
Lei Zhangb36e7042015-10-28 13:40:52 -0400831int32_t spvOpcodeIsBasicTypeNullable(SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100832 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400833 case SpvOpTypeBool:
834 case SpvOpTypeInt:
835 case SpvOpTypeFloat:
836 case SpvOpTypePointer:
837 case SpvOpTypeEvent:
838 case SpvOpTypeDeviceEvent:
839 case SpvOpTypeReserveId:
840 case SpvOpTypeQueue:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100841 return true;
842 default:
843 return false;
844 }
845}
846
Lei Zhang1a0334e2015-11-02 09:41:20 -0500847int32_t spvInstructionIsInBasicBlock(const spv_instruction_t* pFirstInst,
848 const spv_instruction_t* pInst) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100849 while (pFirstInst != pInst) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400850 if (SpvOpFunction == pInst->opcode) break;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100851 pInst--;
852 }
Lei Zhangb36e7042015-10-28 13:40:52 -0400853 if (SpvOpFunction != pInst->opcode) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100854 return true;
855}
856
Lei Zhangb36e7042015-10-28 13:40:52 -0400857int32_t spvOpcodeIsValue(SpvOp opcode) {
Lei Zhang40056702015-09-11 14:31:27 -0400858 if (spvOpcodeIsPointer(opcode)) return true;
859 if (spvOpcodeIsConstant(opcode)) return true;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100860 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400861 case SpvOpLoad:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100862 // TODO: Other Opcode's resulting in a value
863 return true;
864 default:
865 return false;
866 }
867}
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400868
Lei Zhangb36e7042015-10-28 13:40:52 -0400869int32_t spvOpcodeGeneratesType(SpvOp op) {
Lei Zhang1a0334e2015-11-02 09:41:20 -0500870 switch (op) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400871 case SpvOpTypeVoid:
872 case SpvOpTypeBool:
873 case SpvOpTypeInt:
874 case SpvOpTypeFloat:
875 case SpvOpTypeVector:
876 case SpvOpTypeMatrix:
877 case SpvOpTypeImage:
878 case SpvOpTypeSampler:
879 case SpvOpTypeSampledImage:
880 case SpvOpTypeArray:
881 case SpvOpTypeRuntimeArray:
882 case SpvOpTypeStruct:
883 case SpvOpTypeOpaque:
884 case SpvOpTypePointer:
885 case SpvOpTypeFunction:
886 case SpvOpTypeEvent:
887 case SpvOpTypeDeviceEvent:
888 case SpvOpTypeReserveId:
889 case SpvOpTypeQueue:
890 case SpvOpTypePipe:
891 case SpvOpTypeForwardPointer:
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400892 return true;
893 default:;
894 }
895 return 0;
896}