blob: b9ad3775a790c324cbae0f632df8b667023670c4 [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
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010027#include "opcode.h"
28
29#include <assert.h>
30#include <string.h>
31
Lei Zhang923f6c12015-11-11 12:45:23 -050032#include "endian.h"
33#include "instruction.h"
34#include "libspirv/libspirv.h"
Lei Zhangaa056cd2015-11-11 14:24:04 -050035#include "spirv_constant.h"
Lei Zhang923f6c12015-11-11 12:45:23 -050036
David Neto78c3b432015-08-27 13:03:52 -040037namespace {
38
39// Descriptions of each opcode. Each entry describes the format of the
40// instruction that follows a particular opcode.
41//
42// Most fields are initialized statically by including an automatically
43// generated file.
44// The operandTypes fields are initialized during spvOpcodeInitialize().
45//
46// TODO(dneto): Some of the macros are quite unreadable. We could make
47// good use of constexpr functions, but some compilers don't support that yet.
48spv_opcode_desc_t opcodeTableEntries[] = {
Lei Zhang1a0334e2015-11-02 09:41:20 -050049#define EmptyList \
50 {}
51#define List(...) \
52 { __VA_ARGS__ }
Lei Zhangb36e7042015-10-28 13:40:52 -040053#define Capability(X) SPV_CAPABILITY_AS_MASK(SpvCapability##X)
Lei Zhang1a0334e2015-11-02 09:41:20 -050054#define Capability2(X, Y) Capability(X) | Capability(Y)
55#define SpvCapabilityNone \
56 0 // Needed so Capability(None) still expands to valid syntax.
David Neto201caf72015-11-04 17:38:17 -050057#define Instruction(Name, HasResult, HasType, NumLogicalOperands, \
58 NumCapabilities, CapabilityRequired, IsVariable, \
59 LogicalArgsList) \
60 {#Name, SpvOp##Name, (NumCapabilities) ? (CapabilityRequired) : 0, \
61 0, {}, /* Filled in later. Operand list, including \
62 result id and type id, if needed */ \
63 HasResult, HasType, LogicalArgsList},
David Neto78c3b432015-08-27 13:03:52 -040064#include "opcode.inc"
65#undef EmptyList
66#undef List
67#undef Capability
Dejan Mircevski205408b2015-09-30 16:42:34 -040068#undef Capability2
David Neto78c3b432015-08-27 13:03:52 -040069#undef CapabilityNone
70#undef Instruction
71};
72
73// Has the opcodeTableEntries table been fully elaborated?
74// That is, are the operandTypes fields initialized?
75bool opcodeTableInitialized = false;
76
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010077// Opcode API
78
David Neto78c3b432015-08-27 13:03:52 -040079// Converts the given operand class enum (from the SPIR-V document generation
David Neto0f166be2015-11-11 01:56:49 -050080// logic) to the operand type required by the parser. The SPV_OPERAND_TYPE_NONE
81// value indicates there is no current operand and no further operands.
David Neto78c3b432015-08-27 13:03:52 -040082// This only applies to logical operands.
Lei Zhangb36e7042015-10-28 13:40:52 -040083spv_operand_type_t convertOperandClassToType(SpvOp opcode,
84 OperandClass operandClass) {
David Neto78c3b432015-08-27 13:03:52 -040085 // The spec document generator uses OptionalOperandLiteral for several kinds
86 // of repeating values. Our parser needs more specific information about
87 // what is being repeated.
88 if (operandClass == OperandOptionalLiteral) {
Lei Zhang40056702015-09-11 14:31:27 -040089 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -040090 case SpvOpLoad:
91 case SpvOpStore:
92 case SpvOpCopyMemory:
93 case SpvOpCopyMemorySized:
David Neto3fca4cd2015-09-17 17:39:45 -040094 // Expect an optional mask. When the Aligned bit is set in the mask,
95 // we will later add the expectation of a literal number operand.
96 return SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS;
Lei Zhangb36e7042015-10-28 13:40:52 -040097 case SpvOpExecutionMode:
David Neto78c3b432015-08-27 13:03:52 -040098 return SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE;
99 default:
100 break;
101 }
Lei Zhangb41d1502015-09-14 15:22:23 -0400102 } else if (operandClass == OperandVariableLiterals) {
David Neto201caf72015-11-04 17:38:17 -0500103 if (opcode == SpvOpConstant || opcode == SpvOpSpecConstant) {
104 // The number type is determined by the type Id operand.
105 return SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER;
106 }
David Neto78c3b432015-08-27 13:03:52 -0400107 }
108
Lei Zhang1a0334e2015-11-02 09:41:20 -0500109 switch (operandClass) {
110 case OperandNone:
111 return SPV_OPERAND_TYPE_NONE;
112 case OperandId:
113 return SPV_OPERAND_TYPE_ID;
114 case OperandOptionalId:
115 return SPV_OPERAND_TYPE_OPTIONAL_ID;
116 case OperandOptionalImage:
117 return SPV_OPERAND_TYPE_OPTIONAL_IMAGE;
118 case OperandVariableIds:
David Neto0f166be2015-11-11 01:56:49 -0500119 if (opcode == SpvOpSpecConstantOp) {
120 // These are the operands to the specialization constant opcode.
121 // The assembler and binary parser set up the extra Id and literal
122 // arguments when processing the opcode operand. So don't add
123 // an operand type for them here.
124 return SPV_OPERAND_TYPE_NONE;
125 }
Lei Zhang1a0334e2015-11-02 09:41:20 -0500126 return SPV_OPERAND_TYPE_VARIABLE_ID;
David Neto561dc4e2015-09-25 14:23:29 -0400127 // The spec only uses OptionalLiteral for an optional literal number.
Lei Zhang1a0334e2015-11-02 09:41:20 -0500128 case OperandOptionalLiteral:
129 return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER;
130 case OperandOptionalLiteralString:
131 return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING;
David Neto561dc4e2015-09-25 14:23:29 -0400132 // This is only used for sequences of literal numbers.
Lei Zhang1a0334e2015-11-02 09:41:20 -0500133 case OperandVariableLiterals:
134 return SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER;
David Neto445ce442015-10-15 15:22:06 -0400135 case OperandLiteralNumber:
Lei Zhangb36e7042015-10-28 13:40:52 -0400136 if (opcode == SpvOpExtInst) {
David Neto445ce442015-10-15 15:22:06 -0400137 // We use a special operand type for the extension instruction number.
Lei Zhang1a0334e2015-11-02 09:41:20 -0500138 // For now, we assume there is only one LiteraNumber argument to
139 // OpExtInst, and it is the extension instruction argument.
David Neto445ce442015-10-15 15:22:06 -0400140 // See the ExtInst entry in opcode.inc
141 // TODO(dneto): Use a function to confirm the assumption, and to verify
142 // that the index into the operandClass is 1, as expected.
143 return SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER;
David Neto0f166be2015-11-11 01:56:49 -0500144 } else if (opcode == SpvOpSpecConstantOp) {
145 // Use a special operand type for the opcode operand, so we can
146 // use mnemonic names instead of the numbers. For example, the
147 // assembler should accept "IAdd" instead of the numeric value of
148 // SpvOpIAdd.
149 return SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER;
David Neto445ce442015-10-15 15:22:06 -0400150 }
151 return SPV_OPERAND_TYPE_LITERAL_INTEGER;
Lei Zhang1a0334e2015-11-02 09:41:20 -0500152 case OperandLiteralString:
153 return SPV_OPERAND_TYPE_LITERAL_STRING;
154 case OperandSource:
155 return SPV_OPERAND_TYPE_SOURCE_LANGUAGE;
156 case OperandExecutionModel:
157 return SPV_OPERAND_TYPE_EXECUTION_MODEL;
158 case OperandAddressing:
159 return SPV_OPERAND_TYPE_ADDRESSING_MODEL;
160 case OperandMemory:
161 return SPV_OPERAND_TYPE_MEMORY_MODEL;
162 case OperandExecutionMode:
163 return SPV_OPERAND_TYPE_EXECUTION_MODE;
164 case OperandStorage:
165 return SPV_OPERAND_TYPE_STORAGE_CLASS;
166 case OperandDimensionality:
167 return SPV_OPERAND_TYPE_DIMENSIONALITY;
168 case OperandSamplerAddressingMode:
169 return SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE;
170 case OperandSamplerFilterMode:
171 return SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE;
172 case OperandSamplerImageFormat:
173 return SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT;
David Neto7cefb232015-09-28 15:33:49 -0400174 case OperandImageChannelOrder:
175 // This is only used to describe the value generated by OpImageQueryOrder.
176 // It is not used as an operand.
177 break;
178 case OperandImageChannelDataType:
Lei Zhang1a0334e2015-11-02 09:41:20 -0500179 // This is only used to describe the value generated by
180 // OpImageQueryFormat. It is not used as an operand.
David Neto7cefb232015-09-28 15:33:49 -0400181 break;
182 case OperandImageOperands:
Dejan Mircevskif8e091a2015-10-13 14:41:31 -0400183 // This is not used in opcode.inc. It only exists to generate the
184 // corresponding spec section. In parsing, image operands meld into the
185 // OperandOptionalImage case.
David Neto7cefb232015-09-28 15:33:49 -0400186 break;
Lei Zhang1a0334e2015-11-02 09:41:20 -0500187 case OperandFPFastMath:
188 return SPV_OPERAND_TYPE_FP_FAST_MATH_MODE;
189 case OperandFPRoundingMode:
190 return SPV_OPERAND_TYPE_FP_ROUNDING_MODE;
191 case OperandLinkageType:
192 return SPV_OPERAND_TYPE_LINKAGE_TYPE;
193 case OperandAccessQualifier:
194 return SPV_OPERAND_TYPE_ACCESS_QUALIFIER;
195 case OperandFuncParamAttr:
196 return SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE;
197 case OperandDecoration:
198 return SPV_OPERAND_TYPE_DECORATION;
199 case OperandBuiltIn:
200 return SPV_OPERAND_TYPE_BUILT_IN;
201 case OperandSelect:
202 return SPV_OPERAND_TYPE_SELECTION_CONTROL;
203 case OperandLoop:
204 return SPV_OPERAND_TYPE_LOOP_CONTROL;
205 case OperandFunction:
206 return SPV_OPERAND_TYPE_FUNCTION_CONTROL;
207 case OperandMemorySemantics:
208 return SPV_OPERAND_TYPE_MEMORY_SEMANTICS;
David Neto78c3b432015-08-27 13:03:52 -0400209 case OperandMemoryAccess:
David Neto7cefb232015-09-28 15:33:49 -0400210 // This case does not occur in the table for SPIR-V 0.99 Rev 32.
David Neto3fca4cd2015-09-17 17:39:45 -0400211 // We expect that it will become SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
David Neto78c3b432015-08-27 13:03:52 -0400212 // and we can remove the special casing above for memory operation
213 // instructions.
214 break;
Lei Zhang1a0334e2015-11-02 09:41:20 -0500215 case OperandScope:
216 return SPV_OPERAND_TYPE_EXECUTION_SCOPE;
217 case OperandGroupOperation:
218 return SPV_OPERAND_TYPE_GROUP_OPERATION;
219 case OperandKernelEnqueueFlags:
220 return SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS;
221 case OperandKernelProfilingInfo:
222 return SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO;
223 case OperandCapability:
224 return SPV_OPERAND_TYPE_CAPABILITY;
David Neto78c3b432015-08-27 13:03:52 -0400225
226 // Used by GroupMemberDecorate
Lei Zhang1a0334e2015-11-02 09:41:20 -0500227 case OperandVariableIdLiteral:
228 return SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER;
David Neto78c3b432015-08-27 13:03:52 -0400229
230 // Used by Switch
Lei Zhang1a0334e2015-11-02 09:41:20 -0500231 case OperandVariableLiteralId:
232 return SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID;
David Neto78c3b432015-08-27 13:03:52 -0400233
234 // These exceptional cases shouldn't occur.
235 case OperandCount:
236 default:
237 break;
238 }
239 assert(0 && "Unexpected operand class");
240 return SPV_OPERAND_TYPE_NONE;
241}
242
Lei Zhanga94701d2015-09-14 10:05:37 -0400243} // anonymous namespace
David Neto78c3b432015-08-27 13:03:52 -0400244
245// Finish populating the opcodeTableEntries array.
246void spvOpcodeTableInitialize() {
247 // Compute the operandTypes field for each entry.
Lei Zhang1a0334e2015-11-02 09:41:20 -0500248 for (auto& opcode : opcodeTableEntries) {
David Neto78c3b432015-08-27 13:03:52 -0400249 opcode.numTypes = 0;
250 // Type ID always comes first, if present.
251 if (opcode.hasType)
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400252 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_TYPE_ID;
David Neto78c3b432015-08-27 13:03:52 -0400253 // Result ID always comes next, if present
254 if (opcode.hasResult)
255 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_RESULT_ID;
Lei Zhanga94701d2015-09-14 10:05:37 -0400256 const uint16_t maxNumOperands =
257 sizeof(opcode.operandTypes) / sizeof(opcode.operandTypes[0]);
258 const uint16_t maxNumClasses =
259 sizeof(opcode.operandClass) / sizeof(opcode.operandClass[0]);
260 for (uint16_t classIndex = 0;
261 opcode.numTypes < maxNumOperands && classIndex < maxNumClasses;
262 classIndex++) {
David Neto78c3b432015-08-27 13:03:52 -0400263 const OperandClass operandClass = opcode.operandClass[classIndex];
David Neto0f166be2015-11-11 01:56:49 -0500264 const auto operandType =
Lei Zhanga94701d2015-09-14 10:05:37 -0400265 convertOperandClassToType(opcode.opcode, operandClass);
David Neto0f166be2015-11-11 01:56:49 -0500266 opcode.operandTypes[opcode.numTypes++] = operandType;
David Neto78c3b432015-08-27 13:03:52 -0400267 // The OperandNone value is not explicitly represented in the .inc file.
268 // However, it is the zero value, and is created via implicit value
David Neto0f166be2015-11-11 01:56:49 -0500269 // initialization. It converts to SPV_OPERAND_TYPE_NONE.
270 // The SPV_OPERAND_TYPE_NONE operand type indicates no current or futher
271 // operands.
272 if (operandType == SPV_OPERAND_TYPE_NONE) {
David Neto78c3b432015-08-27 13:03:52 -0400273 opcode.numTypes--;
274 break;
275 }
276 }
David Neto0f166be2015-11-11 01:56:49 -0500277
David Neto78c3b432015-08-27 13:03:52 -0400278 // We should have written the terminating SPV_OPERAND_TYPE_NONE entry, but
279 // also without overflowing.
Lei Zhanga94701d2015-09-14 10:05:37 -0400280 assert((opcode.numTypes < maxNumOperands) &&
281 "Operand class list is too long. Expand "
282 "spv_opcode_desc_t.operandClass");
David Neto78c3b432015-08-27 13:03:52 -0400283 }
284 opcodeTableInitialized = true;
285}
286
Lei Zhang1a0334e2015-11-02 09:41:20 -0500287const char* spvGeneratorStr(uint32_t generator) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100288 switch (generator) {
289 case SPV_GENERATOR_KHRONOS:
290 return "Khronos";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100291 case SPV_GENERATOR_LUNARG:
292 return "LunarG";
David Neto1780fc42015-10-26 15:43:12 -0400293 case SPV_GENERATOR_VALVE:
294 return "Valve";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100295 case SPV_GENERATOR_CODEPLAY:
296 return "Codeplay Software Ltd.";
David Neto1780fc42015-10-26 15:43:12 -0400297 case SPV_GENERATOR_NVIDIA:
298 return "NVIDIA";
299 case SPV_GENERATOR_ARM:
300 return "ARM";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100301 default:
302 return "Unknown";
303 }
304}
305
Lei Zhangb36e7042015-10-28 13:40:52 -0400306uint32_t spvOpcodeMake(uint16_t wordCount, SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100307 return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
308}
309
Lei Zhang1a0334e2015-11-02 09:41:20 -0500310void spvOpcodeSplit(const uint32_t word, uint16_t* pWordCount, SpvOp* pOpcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100311 if (pWordCount) {
312 *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
313 }
314 if (pOpcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400315 *pOpcode = (SpvOp)(0x0000ffff & word);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100316 }
317}
318
Lei Zhang1a0334e2015-11-02 09:41:20 -0500319spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable) {
Lei Zhang40056702015-09-11 14:31:27 -0400320 if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100321
David Neto78c3b432015-08-27 13:03:52 -0400322 static spv_opcode_table_t table = {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100323 sizeof(opcodeTableEntries) / sizeof(spv_opcode_desc_t),
324 opcodeTableEntries};
325
David Neto78c3b432015-08-27 13:03:52 -0400326 // TODO(dneto): Consider thread safety of initialization.
327 // That is, ordering effects of the flag vs. the table updates.
Lei Zhang40056702015-09-11 14:31:27 -0400328 if (!opcodeTableInitialized) spvOpcodeTableInitialize();
David Neto78c3b432015-08-27 13:03:52 -0400329
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100330 *pInstTable = &table;
331
332 return SPV_SUCCESS;
333}
334
335spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500336 const char* name,
337 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400338 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
339 if (!table) return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100340
341 // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
342 // preferable but the table requires sorting on the Opcode name, but it's
343 // static
344 // const initialized and matches the order of the spec.
345 const size_t nameLength = strlen(name);
346 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
347 if (nameLength == strlen(table->entries[opcodeIndex].name) &&
348 !strncmp(name, table->entries[opcodeIndex].name, nameLength)) {
349 // NOTE: Found out Opcode!
350 *pEntry = &table->entries[opcodeIndex];
351 return SPV_SUCCESS;
352 }
353 }
354
355 return SPV_ERROR_INVALID_LOOKUP;
356}
357
358spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
Lei Zhangb36e7042015-10-28 13:40:52 -0400359 const SpvOp opcode,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500360 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400361 if (!table) return SPV_ERROR_INVALID_TABLE;
362 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100363
364 // TODO: As above this lookup is not optimal.
365 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
366 if (opcode == table->entries[opcodeIndex].opcode) {
367 // NOTE: Found the Opcode!
368 *pEntry = &table->entries[opcodeIndex];
369 return SPV_SUCCESS;
370 }
371 }
372
373 return SPV_ERROR_INVALID_LOOKUP;
374}
375
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100376int32_t spvOpcodeRequiresCapabilities(spv_opcode_desc entry) {
David Neto9db3a532015-10-07 16:58:38 -0400377 return entry->capabilities != 0;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100378}
379
Lei Zhang1a0334e2015-11-02 09:41:20 -0500380void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100381 const uint16_t wordCount, const spv_endianness_t endian,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500382 spv_instruction_t* pInst) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100383 pInst->opcode = opcode;
David Netob5dc8fc2015-10-06 16:22:00 -0400384 pInst->words.resize(wordCount);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100385 for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
386 pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
387 if (!wordIndex) {
388 uint16_t thisWordCount;
Lei Zhangb36e7042015-10-28 13:40:52 -0400389 SpvOp thisOpcode;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100390 spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
391 assert(opcode == thisOpcode && wordCount == thisWordCount &&
392 "Endianness failed!");
393 }
394 }
395}
396
Lei Zhang1a0334e2015-11-02 09:41:20 -0500397const char* spvOpcodeString(const SpvOp opcode) {
David Neto201caf72015-11-04 17:38:17 -0500398// Use the syntax table so it's sure to be complete.
David Neto1bcd3d12015-11-02 16:03:12 -0500399#define Instruction(Name, ...) \
400 case SpvOp##Name: \
401 return #Name;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100402 switch (opcode) {
David Neto1bcd3d12015-11-02 16:03:12 -0500403#include "opcode.inc"
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100404 default:
405 assert(0 && "Unreachable!");
406 }
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100407 return "unknown";
David Neto1bcd3d12015-11-02 16:03:12 -0500408#undef Instruction
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100409}
410
Lei Zhangb36e7042015-10-28 13:40:52 -0400411int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100412 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400413 case SpvOpTypeInt:
414 case SpvOpTypeFloat:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100415 return true;
416 default:
417 return false;
418 }
419}
420
Lei Zhangb36e7042015-10-28 13:40:52 -0400421int32_t spvOpcodeIsConstant(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100422 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400423 case SpvOpConstantTrue:
424 case SpvOpConstantFalse:
425 case SpvOpConstant:
426 case SpvOpConstantComposite:
427 case SpvOpConstantSampler:
428 // case SpvOpConstantNull:
429 case SpvOpConstantNull:
430 case SpvOpSpecConstantTrue:
431 case SpvOpSpecConstantFalse:
432 case SpvOpSpecConstant:
433 case SpvOpSpecConstantComposite:
434 // case SpvOpSpecConstantOp:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100435 return true;
436 default:
437 return false;
438 }
439}
440
Lei Zhangb36e7042015-10-28 13:40:52 -0400441int32_t spvOpcodeIsComposite(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100442 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400443 case SpvOpTypeVector:
444 case SpvOpTypeMatrix:
445 case SpvOpTypeArray:
446 case SpvOpTypeStruct:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100447 return true;
448 default:
449 return false;
450 }
451}
452
Lei Zhang1a0334e2015-11-02 09:41:20 -0500453int32_t spvOpcodeAreTypesEqual(const spv_instruction_t* pTypeInst0,
454 const spv_instruction_t* pTypeInst1) {
Lei Zhang40056702015-09-11 14:31:27 -0400455 if (pTypeInst0->opcode != pTypeInst1->opcode) return false;
456 if (pTypeInst0->words[1] != pTypeInst1->words[1]) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100457 return true;
458}
459
Lei Zhangb36e7042015-10-28 13:40:52 -0400460int32_t spvOpcodeIsPointer(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100461 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400462 case SpvOpVariable:
463 case SpvOpAccessChain:
464 case SpvOpInBoundsAccessChain:
465 case SpvOpFunctionParameter:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100466 return true;
467 default:
468 return false;
469 }
470}
471
Lei Zhangb36e7042015-10-28 13:40:52 -0400472int32_t spvOpcodeIsObject(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100473 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400474 case SpvOpConstantTrue:
475 case SpvOpConstantFalse:
476 case SpvOpConstant:
477 case SpvOpConstantComposite:
478 // TODO: case SpvOpConstantSampler:
479 case SpvOpConstantNull:
480 case SpvOpSpecConstantTrue:
481 case SpvOpSpecConstantFalse:
482 case SpvOpSpecConstant:
483 case SpvOpSpecConstantComposite:
484 // TODO: case SpvOpSpecConstantOp:
485 case SpvOpVariable:
486 case SpvOpAccessChain:
487 case SpvOpInBoundsAccessChain:
488 case SpvOpConvertFToU:
489 case SpvOpConvertFToS:
490 case SpvOpConvertSToF:
491 case SpvOpConvertUToF:
492 case SpvOpUConvert:
493 case SpvOpSConvert:
494 case SpvOpFConvert:
495 case SpvOpConvertPtrToU:
496 // TODO: case SpvOpConvertUToPtr:
497 case SpvOpPtrCastToGeneric:
498 // TODO: case SpvOpGenericCastToPtr:
499 case SpvOpBitcast:
500 // TODO: case SpvOpGenericCastToPtrExplicit:
501 case SpvOpSatConvertSToU:
502 case SpvOpSatConvertUToS:
503 case SpvOpVectorExtractDynamic:
504 case SpvOpCompositeConstruct:
505 case SpvOpCompositeExtract:
506 case SpvOpCopyObject:
507 case SpvOpTranspose:
508 case SpvOpSNegate:
509 case SpvOpFNegate:
510 case SpvOpNot:
511 case SpvOpIAdd:
512 case SpvOpFAdd:
513 case SpvOpISub:
514 case SpvOpFSub:
515 case SpvOpIMul:
516 case SpvOpFMul:
517 case SpvOpUDiv:
518 case SpvOpSDiv:
519 case SpvOpFDiv:
520 case SpvOpUMod:
521 case SpvOpSRem:
522 case SpvOpSMod:
523 case SpvOpVectorTimesScalar:
524 case SpvOpMatrixTimesScalar:
525 case SpvOpVectorTimesMatrix:
526 case SpvOpMatrixTimesVector:
527 case SpvOpMatrixTimesMatrix:
528 case SpvOpOuterProduct:
529 case SpvOpDot:
530 case SpvOpShiftRightLogical:
531 case SpvOpShiftRightArithmetic:
532 case SpvOpShiftLeftLogical:
533 case SpvOpBitwiseOr:
534 case SpvOpBitwiseXor:
535 case SpvOpBitwiseAnd:
536 case SpvOpAny:
537 case SpvOpAll:
538 case SpvOpIsNan:
539 case SpvOpIsInf:
540 case SpvOpIsFinite:
541 case SpvOpIsNormal:
542 case SpvOpSignBitSet:
543 case SpvOpLessOrGreater:
544 case SpvOpOrdered:
545 case SpvOpUnordered:
546 case SpvOpLogicalOr:
547 case SpvOpLogicalAnd:
548 case SpvOpSelect:
549 case SpvOpIEqual:
550 case SpvOpFOrdEqual:
551 case SpvOpFUnordEqual:
552 case SpvOpINotEqual:
553 case SpvOpFOrdNotEqual:
554 case SpvOpFUnordNotEqual:
555 case SpvOpULessThan:
556 case SpvOpSLessThan:
557 case SpvOpFOrdLessThan:
558 case SpvOpFUnordLessThan:
559 case SpvOpUGreaterThan:
560 case SpvOpSGreaterThan:
561 case SpvOpFOrdGreaterThan:
562 case SpvOpFUnordGreaterThan:
563 case SpvOpULessThanEqual:
564 case SpvOpSLessThanEqual:
565 case SpvOpFOrdLessThanEqual:
566 case SpvOpFUnordLessThanEqual:
567 case SpvOpUGreaterThanEqual:
568 case SpvOpSGreaterThanEqual:
569 case SpvOpFOrdGreaterThanEqual:
570 case SpvOpFUnordGreaterThanEqual:
571 case SpvOpDPdx:
572 case SpvOpDPdy:
573 case SpvOpFwidth:
574 case SpvOpDPdxFine:
575 case SpvOpDPdyFine:
576 case SpvOpFwidthFine:
577 case SpvOpDPdxCoarse:
578 case SpvOpDPdyCoarse:
579 case SpvOpFwidthCoarse:
580 case SpvOpReturnValue:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100581 return true;
582 default:
583 return false;
584 }
585}
586
Lei Zhangb36e7042015-10-28 13:40:52 -0400587int32_t spvOpcodeIsBasicTypeNullable(SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100588 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400589 case SpvOpTypeBool:
590 case SpvOpTypeInt:
591 case SpvOpTypeFloat:
592 case SpvOpTypePointer:
593 case SpvOpTypeEvent:
594 case SpvOpTypeDeviceEvent:
595 case SpvOpTypeReserveId:
596 case SpvOpTypeQueue:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100597 return true;
598 default:
599 return false;
600 }
601}
602
Lei Zhang1a0334e2015-11-02 09:41:20 -0500603int32_t spvInstructionIsInBasicBlock(const spv_instruction_t* pFirstInst,
604 const spv_instruction_t* pInst) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100605 while (pFirstInst != pInst) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400606 if (SpvOpFunction == pInst->opcode) break;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100607 pInst--;
608 }
Lei Zhangb36e7042015-10-28 13:40:52 -0400609 if (SpvOpFunction != pInst->opcode) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100610 return true;
611}
612
Lei Zhangb36e7042015-10-28 13:40:52 -0400613int32_t spvOpcodeIsValue(SpvOp opcode) {
Lei Zhang40056702015-09-11 14:31:27 -0400614 if (spvOpcodeIsPointer(opcode)) return true;
615 if (spvOpcodeIsConstant(opcode)) return true;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100616 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400617 case SpvOpLoad:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100618 // TODO: Other Opcode's resulting in a value
619 return true;
620 default:
621 return false;
622 }
623}
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400624
Lei Zhangb36e7042015-10-28 13:40:52 -0400625int32_t spvOpcodeGeneratesType(SpvOp op) {
Lei Zhang1a0334e2015-11-02 09:41:20 -0500626 switch (op) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400627 case SpvOpTypeVoid:
628 case SpvOpTypeBool:
629 case SpvOpTypeInt:
630 case SpvOpTypeFloat:
631 case SpvOpTypeVector:
632 case SpvOpTypeMatrix:
633 case SpvOpTypeImage:
634 case SpvOpTypeSampler:
635 case SpvOpTypeSampledImage:
636 case SpvOpTypeArray:
637 case SpvOpTypeRuntimeArray:
638 case SpvOpTypeStruct:
639 case SpvOpTypeOpaque:
640 case SpvOpTypePointer:
641 case SpvOpTypeFunction:
642 case SpvOpTypeEvent:
643 case SpvOpTypeDeviceEvent:
644 case SpvOpTypeReserveId:
645 case SpvOpTypeQueue:
646 case SpvOpTypePipe:
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400647 return true;
David Netoaef608c2015-11-02 14:59:02 -0500648 default:
649 // In particular, OpTypeForwardPointer does not generate a type,
650 // but declares a storage class for a pointer type generated
651 // by a different instruction.
652 break;
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400653 }
654 return 0;
655}