blob: c78997c7936657f0ef0e70477bcf5d7597879770 [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 Zhang4ac601a2015-11-11 17:29:23 -050036#include "spirv_operands.h"
Lei Zhang923f6c12015-11-11 12:45:23 -050037
David Neto78c3b432015-08-27 13:03:52 -040038namespace {
39
40// Descriptions of each opcode. Each entry describes the format of the
41// instruction that follows a particular opcode.
42//
43// Most fields are initialized statically by including an automatically
44// generated file.
45// The operandTypes fields are initialized during spvOpcodeInitialize().
46//
47// TODO(dneto): Some of the macros are quite unreadable. We could make
48// good use of constexpr functions, but some compilers don't support that yet.
49spv_opcode_desc_t opcodeTableEntries[] = {
Lei Zhang1a0334e2015-11-02 09:41:20 -050050#define EmptyList \
51 {}
52#define List(...) \
53 { __VA_ARGS__ }
Lei Zhangb36e7042015-10-28 13:40:52 -040054#define Capability(X) SPV_CAPABILITY_AS_MASK(SpvCapability##X)
Lei Zhang1a0334e2015-11-02 09:41:20 -050055#define Capability2(X, Y) Capability(X) | Capability(Y)
56#define SpvCapabilityNone \
57 0 // Needed so Capability(None) still expands to valid syntax.
David Neto201caf72015-11-04 17:38:17 -050058#define Instruction(Name, HasResult, HasType, NumLogicalOperands, \
59 NumCapabilities, CapabilityRequired, IsVariable, \
60 LogicalArgsList) \
61 {#Name, SpvOp##Name, (NumCapabilities) ? (CapabilityRequired) : 0, \
62 0, {}, /* Filled in later. Operand list, including \
63 result id and type id, if needed */ \
64 HasResult, HasType, LogicalArgsList},
David Neto78c3b432015-08-27 13:03:52 -040065#include "opcode.inc"
66#undef EmptyList
67#undef List
68#undef Capability
Dejan Mircevski205408b2015-09-30 16:42:34 -040069#undef Capability2
David Neto78c3b432015-08-27 13:03:52 -040070#undef CapabilityNone
71#undef Instruction
72};
73
74// Has the opcodeTableEntries table been fully elaborated?
75// That is, are the operandTypes fields initialized?
76bool opcodeTableInitialized = false;
77
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010078// Opcode API
79
David Neto78c3b432015-08-27 13:03:52 -040080// Converts the given operand class enum (from the SPIR-V document generation
David Neto0f166be2015-11-11 01:56:49 -050081// logic) to the operand type required by the parser. The SPV_OPERAND_TYPE_NONE
82// value indicates there is no current operand and no further operands.
David Neto78c3b432015-08-27 13:03:52 -040083// 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) {
David Neto201caf72015-11-04 17:38:17 -0500104 if (opcode == SpvOpConstant || opcode == SpvOpSpecConstant) {
105 // The number type is determined by the type Id operand.
106 return SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER;
107 }
David Neto78c3b432015-08-27 13:03:52 -0400108 }
109
Lei Zhang1a0334e2015-11-02 09:41:20 -0500110 switch (operandClass) {
111 case OperandNone:
112 return SPV_OPERAND_TYPE_NONE;
113 case OperandId:
114 return SPV_OPERAND_TYPE_ID;
115 case OperandOptionalId:
116 return SPV_OPERAND_TYPE_OPTIONAL_ID;
117 case OperandOptionalImage:
118 return SPV_OPERAND_TYPE_OPTIONAL_IMAGE;
119 case OperandVariableIds:
David Neto0f166be2015-11-11 01:56:49 -0500120 if (opcode == SpvOpSpecConstantOp) {
121 // These are the operands to the specialization constant opcode.
122 // The assembler and binary parser set up the extra Id and literal
123 // arguments when processing the opcode operand. So don't add
124 // an operand type for them here.
125 return SPV_OPERAND_TYPE_NONE;
126 }
Lei Zhang1a0334e2015-11-02 09:41:20 -0500127 return SPV_OPERAND_TYPE_VARIABLE_ID;
David Neto561dc4e2015-09-25 14:23:29 -0400128 // The spec only uses OptionalLiteral for an optional literal number.
Lei Zhang1a0334e2015-11-02 09:41:20 -0500129 case OperandOptionalLiteral:
130 return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER;
131 case OperandOptionalLiteralString:
132 return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING;
David Neto561dc4e2015-09-25 14:23:29 -0400133 // This is only used for sequences of literal numbers.
Lei Zhang1a0334e2015-11-02 09:41:20 -0500134 case OperandVariableLiterals:
135 return SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER;
David Neto445ce442015-10-15 15:22:06 -0400136 case OperandLiteralNumber:
Lei Zhangb36e7042015-10-28 13:40:52 -0400137 if (opcode == SpvOpExtInst) {
David Neto445ce442015-10-15 15:22:06 -0400138 // We use a special operand type for the extension instruction number.
Lei Zhang1a0334e2015-11-02 09:41:20 -0500139 // For now, we assume there is only one LiteraNumber argument to
140 // OpExtInst, and it is the extension instruction argument.
David Neto445ce442015-10-15 15:22:06 -0400141 // See the ExtInst entry in opcode.inc
142 // TODO(dneto): Use a function to confirm the assumption, and to verify
143 // that the index into the operandClass is 1, as expected.
144 return SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER;
David Neto0f166be2015-11-11 01:56:49 -0500145 } else if (opcode == SpvOpSpecConstantOp) {
146 // Use a special operand type for the opcode operand, so we can
147 // use mnemonic names instead of the numbers. For example, the
148 // assembler should accept "IAdd" instead of the numeric value of
149 // SpvOpIAdd.
150 return SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER;
David Neto445ce442015-10-15 15:22:06 -0400151 }
152 return SPV_OPERAND_TYPE_LITERAL_INTEGER;
Lei Zhang1a0334e2015-11-02 09:41:20 -0500153 case OperandLiteralString:
154 return SPV_OPERAND_TYPE_LITERAL_STRING;
155 case OperandSource:
156 return SPV_OPERAND_TYPE_SOURCE_LANGUAGE;
157 case OperandExecutionModel:
158 return SPV_OPERAND_TYPE_EXECUTION_MODEL;
159 case OperandAddressing:
160 return SPV_OPERAND_TYPE_ADDRESSING_MODEL;
161 case OperandMemory:
162 return SPV_OPERAND_TYPE_MEMORY_MODEL;
163 case OperandExecutionMode:
164 return SPV_OPERAND_TYPE_EXECUTION_MODE;
165 case OperandStorage:
166 return SPV_OPERAND_TYPE_STORAGE_CLASS;
167 case OperandDimensionality:
168 return SPV_OPERAND_TYPE_DIMENSIONALITY;
169 case OperandSamplerAddressingMode:
170 return SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE;
171 case OperandSamplerFilterMode:
172 return SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE;
173 case OperandSamplerImageFormat:
174 return SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT;
David Neto7cefb232015-09-28 15:33:49 -0400175 case OperandImageChannelOrder:
176 // This is only used to describe the value generated by OpImageQueryOrder.
177 // It is not used as an operand.
178 break;
179 case OperandImageChannelDataType:
Lei Zhang1a0334e2015-11-02 09:41:20 -0500180 // This is only used to describe the value generated by
181 // OpImageQueryFormat. It is not used as an operand.
David Neto7cefb232015-09-28 15:33:49 -0400182 break;
183 case OperandImageOperands:
Dejan Mircevskif8e091a2015-10-13 14:41:31 -0400184 // This is not used in opcode.inc. It only exists to generate the
185 // corresponding spec section. In parsing, image operands meld into the
186 // OperandOptionalImage case.
David Neto7cefb232015-09-28 15:33:49 -0400187 break;
Lei Zhang1a0334e2015-11-02 09:41:20 -0500188 case OperandFPFastMath:
189 return SPV_OPERAND_TYPE_FP_FAST_MATH_MODE;
190 case OperandFPRoundingMode:
191 return SPV_OPERAND_TYPE_FP_ROUNDING_MODE;
192 case OperandLinkageType:
193 return SPV_OPERAND_TYPE_LINKAGE_TYPE;
194 case OperandAccessQualifier:
195 return SPV_OPERAND_TYPE_ACCESS_QUALIFIER;
196 case OperandFuncParamAttr:
197 return SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE;
198 case OperandDecoration:
199 return SPV_OPERAND_TYPE_DECORATION;
200 case OperandBuiltIn:
201 return SPV_OPERAND_TYPE_BUILT_IN;
202 case OperandSelect:
203 return SPV_OPERAND_TYPE_SELECTION_CONTROL;
204 case OperandLoop:
205 return SPV_OPERAND_TYPE_LOOP_CONTROL;
206 case OperandFunction:
207 return SPV_OPERAND_TYPE_FUNCTION_CONTROL;
208 case OperandMemorySemantics:
209 return SPV_OPERAND_TYPE_MEMORY_SEMANTICS;
David Neto78c3b432015-08-27 13:03:52 -0400210 case OperandMemoryAccess:
David Neto7cefb232015-09-28 15:33:49 -0400211 // This case does not occur in the table for SPIR-V 0.99 Rev 32.
David Neto3fca4cd2015-09-17 17:39:45 -0400212 // We expect that it will become SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
David Neto78c3b432015-08-27 13:03:52 -0400213 // and we can remove the special casing above for memory operation
214 // instructions.
215 break;
Lei Zhang1a0334e2015-11-02 09:41:20 -0500216 case OperandScope:
217 return SPV_OPERAND_TYPE_EXECUTION_SCOPE;
218 case OperandGroupOperation:
219 return SPV_OPERAND_TYPE_GROUP_OPERATION;
220 case OperandKernelEnqueueFlags:
221 return SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS;
222 case OperandKernelProfilingInfo:
223 return SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO;
224 case OperandCapability:
225 return SPV_OPERAND_TYPE_CAPABILITY;
David Neto78c3b432015-08-27 13:03:52 -0400226
227 // Used by GroupMemberDecorate
Lei Zhang1a0334e2015-11-02 09:41:20 -0500228 case OperandVariableIdLiteral:
229 return SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER;
David Neto78c3b432015-08-27 13:03:52 -0400230
231 // Used by Switch
Lei Zhang1a0334e2015-11-02 09:41:20 -0500232 case OperandVariableLiteralId:
233 return SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID;
David Neto78c3b432015-08-27 13:03:52 -0400234
235 // These exceptional cases shouldn't occur.
236 case OperandCount:
237 default:
238 break;
239 }
240 assert(0 && "Unexpected operand class");
241 return SPV_OPERAND_TYPE_NONE;
242}
243
Lei Zhanga94701d2015-09-14 10:05:37 -0400244} // anonymous namespace
David Neto78c3b432015-08-27 13:03:52 -0400245
246// Finish populating the opcodeTableEntries array.
247void spvOpcodeTableInitialize() {
248 // Compute the operandTypes field for each entry.
Lei Zhang1a0334e2015-11-02 09:41:20 -0500249 for (auto& opcode : opcodeTableEntries) {
David Neto78c3b432015-08-27 13:03:52 -0400250 opcode.numTypes = 0;
251 // Type ID always comes first, if present.
252 if (opcode.hasType)
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400253 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_TYPE_ID;
David Neto78c3b432015-08-27 13:03:52 -0400254 // Result ID always comes next, if present
255 if (opcode.hasResult)
256 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_RESULT_ID;
Lei Zhanga94701d2015-09-14 10:05:37 -0400257 const uint16_t maxNumOperands =
258 sizeof(opcode.operandTypes) / sizeof(opcode.operandTypes[0]);
259 const uint16_t maxNumClasses =
260 sizeof(opcode.operandClass) / sizeof(opcode.operandClass[0]);
261 for (uint16_t classIndex = 0;
262 opcode.numTypes < maxNumOperands && classIndex < maxNumClasses;
263 classIndex++) {
David Neto78c3b432015-08-27 13:03:52 -0400264 const OperandClass operandClass = opcode.operandClass[classIndex];
David Neto0f166be2015-11-11 01:56:49 -0500265 const auto operandType =
Lei Zhanga94701d2015-09-14 10:05:37 -0400266 convertOperandClassToType(opcode.opcode, operandClass);
David Neto0f166be2015-11-11 01:56:49 -0500267 opcode.operandTypes[opcode.numTypes++] = operandType;
David Neto78c3b432015-08-27 13:03:52 -0400268 // The OperandNone value is not explicitly represented in the .inc file.
269 // However, it is the zero value, and is created via implicit value
David Neto0f166be2015-11-11 01:56:49 -0500270 // initialization. It converts to SPV_OPERAND_TYPE_NONE.
271 // The SPV_OPERAND_TYPE_NONE operand type indicates no current or futher
272 // operands.
273 if (operandType == SPV_OPERAND_TYPE_NONE) {
David Neto78c3b432015-08-27 13:03:52 -0400274 opcode.numTypes--;
275 break;
276 }
277 }
David Neto0f166be2015-11-11 01:56:49 -0500278
David Neto78c3b432015-08-27 13:03:52 -0400279 // We should have written the terminating SPV_OPERAND_TYPE_NONE entry, but
280 // also without overflowing.
Lei Zhanga94701d2015-09-14 10:05:37 -0400281 assert((opcode.numTypes < maxNumOperands) &&
282 "Operand class list is too long. Expand "
283 "spv_opcode_desc_t.operandClass");
David Neto78c3b432015-08-27 13:03:52 -0400284 }
285 opcodeTableInitialized = true;
286}
287
Lei Zhang1a0334e2015-11-02 09:41:20 -0500288const char* spvGeneratorStr(uint32_t generator) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100289 switch (generator) {
290 case SPV_GENERATOR_KHRONOS:
291 return "Khronos";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100292 case SPV_GENERATOR_LUNARG:
293 return "LunarG";
David Neto1780fc42015-10-26 15:43:12 -0400294 case SPV_GENERATOR_VALVE:
295 return "Valve";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100296 case SPV_GENERATOR_CODEPLAY:
297 return "Codeplay Software Ltd.";
David Neto1780fc42015-10-26 15:43:12 -0400298 case SPV_GENERATOR_NVIDIA:
299 return "NVIDIA";
300 case SPV_GENERATOR_ARM:
301 return "ARM";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100302 default:
303 return "Unknown";
304 }
305}
306
Lei Zhangb36e7042015-10-28 13:40:52 -0400307uint32_t spvOpcodeMake(uint16_t wordCount, SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100308 return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
309}
310
Lei Zhang1a0334e2015-11-02 09:41:20 -0500311void spvOpcodeSplit(const uint32_t word, uint16_t* pWordCount, SpvOp* pOpcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100312 if (pWordCount) {
313 *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
314 }
315 if (pOpcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400316 *pOpcode = (SpvOp)(0x0000ffff & word);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100317 }
318}
319
Lei Zhang1a0334e2015-11-02 09:41:20 -0500320spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable) {
Lei Zhang40056702015-09-11 14:31:27 -0400321 if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100322
David Neto78c3b432015-08-27 13:03:52 -0400323 static spv_opcode_table_t table = {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100324 sizeof(opcodeTableEntries) / sizeof(spv_opcode_desc_t),
325 opcodeTableEntries};
326
David Neto78c3b432015-08-27 13:03:52 -0400327 // TODO(dneto): Consider thread safety of initialization.
328 // That is, ordering effects of the flag vs. the table updates.
Lei Zhang40056702015-09-11 14:31:27 -0400329 if (!opcodeTableInitialized) spvOpcodeTableInitialize();
David Neto78c3b432015-08-27 13:03:52 -0400330
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100331 *pInstTable = &table;
332
333 return SPV_SUCCESS;
334}
335
336spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500337 const char* name,
338 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400339 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
340 if (!table) return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100341
342 // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
343 // preferable but the table requires sorting on the Opcode name, but it's
344 // static
345 // const initialized and matches the order of the spec.
346 const size_t nameLength = strlen(name);
347 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
348 if (nameLength == strlen(table->entries[opcodeIndex].name) &&
349 !strncmp(name, table->entries[opcodeIndex].name, nameLength)) {
350 // NOTE: Found out Opcode!
351 *pEntry = &table->entries[opcodeIndex];
352 return SPV_SUCCESS;
353 }
354 }
355
356 return SPV_ERROR_INVALID_LOOKUP;
357}
358
359spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
Lei Zhangb36e7042015-10-28 13:40:52 -0400360 const SpvOp opcode,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500361 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400362 if (!table) return SPV_ERROR_INVALID_TABLE;
363 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100364
365 // TODO: As above this lookup is not optimal.
366 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
367 if (opcode == table->entries[opcodeIndex].opcode) {
368 // NOTE: Found the Opcode!
369 *pEntry = &table->entries[opcodeIndex];
370 return SPV_SUCCESS;
371 }
372 }
373
374 return SPV_ERROR_INVALID_LOOKUP;
375}
376
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100377int32_t spvOpcodeRequiresCapabilities(spv_opcode_desc entry) {
David Neto9db3a532015-10-07 16:58:38 -0400378 return entry->capabilities != 0;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100379}
380
Lei Zhang1a0334e2015-11-02 09:41:20 -0500381void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100382 const uint16_t wordCount, const spv_endianness_t endian,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500383 spv_instruction_t* pInst) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100384 pInst->opcode = opcode;
David Netob5dc8fc2015-10-06 16:22:00 -0400385 pInst->words.resize(wordCount);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100386 for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
387 pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
388 if (!wordIndex) {
389 uint16_t thisWordCount;
Lei Zhangb36e7042015-10-28 13:40:52 -0400390 SpvOp thisOpcode;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100391 spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
392 assert(opcode == thisOpcode && wordCount == thisWordCount &&
393 "Endianness failed!");
394 }
395 }
396}
397
Lei Zhang1a0334e2015-11-02 09:41:20 -0500398const char* spvOpcodeString(const SpvOp opcode) {
David Neto201caf72015-11-04 17:38:17 -0500399// Use the syntax table so it's sure to be complete.
David Neto1bcd3d12015-11-02 16:03:12 -0500400#define Instruction(Name, ...) \
401 case SpvOp##Name: \
402 return #Name;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100403 switch (opcode) {
David Neto1bcd3d12015-11-02 16:03:12 -0500404#include "opcode.inc"
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100405 default:
406 assert(0 && "Unreachable!");
407 }
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100408 return "unknown";
David Neto1bcd3d12015-11-02 16:03:12 -0500409#undef Instruction
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100410}
411
Lei Zhangb36e7042015-10-28 13:40:52 -0400412int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100413 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400414 case SpvOpTypeInt:
415 case SpvOpTypeFloat:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100416 return true;
417 default:
418 return false;
419 }
420}
421
Lei Zhangb36e7042015-10-28 13:40:52 -0400422int32_t spvOpcodeIsConstant(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100423 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400424 case SpvOpConstantTrue:
425 case SpvOpConstantFalse:
426 case SpvOpConstant:
427 case SpvOpConstantComposite:
428 case SpvOpConstantSampler:
429 // case SpvOpConstantNull:
430 case SpvOpConstantNull:
431 case SpvOpSpecConstantTrue:
432 case SpvOpSpecConstantFalse:
433 case SpvOpSpecConstant:
434 case SpvOpSpecConstantComposite:
435 // case SpvOpSpecConstantOp:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100436 return true;
437 default:
438 return false;
439 }
440}
441
Lei Zhangb36e7042015-10-28 13:40:52 -0400442int32_t spvOpcodeIsComposite(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100443 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400444 case SpvOpTypeVector:
445 case SpvOpTypeMatrix:
446 case SpvOpTypeArray:
447 case SpvOpTypeStruct:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100448 return true;
449 default:
450 return false;
451 }
452}
453
Lei Zhang1a0334e2015-11-02 09:41:20 -0500454int32_t spvOpcodeAreTypesEqual(const spv_instruction_t* pTypeInst0,
455 const spv_instruction_t* pTypeInst1) {
Lei Zhang40056702015-09-11 14:31:27 -0400456 if (pTypeInst0->opcode != pTypeInst1->opcode) return false;
457 if (pTypeInst0->words[1] != pTypeInst1->words[1]) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100458 return true;
459}
460
Lei Zhangb36e7042015-10-28 13:40:52 -0400461int32_t spvOpcodeIsPointer(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100462 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400463 case SpvOpVariable:
464 case SpvOpAccessChain:
465 case SpvOpInBoundsAccessChain:
466 case SpvOpFunctionParameter:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100467 return true;
468 default:
469 return false;
470 }
471}
472
Lei Zhangb36e7042015-10-28 13:40:52 -0400473int32_t spvOpcodeIsObject(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100474 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400475 case SpvOpConstantTrue:
476 case SpvOpConstantFalse:
477 case SpvOpConstant:
478 case SpvOpConstantComposite:
479 // TODO: case SpvOpConstantSampler:
480 case SpvOpConstantNull:
481 case SpvOpSpecConstantTrue:
482 case SpvOpSpecConstantFalse:
483 case SpvOpSpecConstant:
484 case SpvOpSpecConstantComposite:
485 // TODO: case SpvOpSpecConstantOp:
486 case SpvOpVariable:
487 case SpvOpAccessChain:
488 case SpvOpInBoundsAccessChain:
489 case SpvOpConvertFToU:
490 case SpvOpConvertFToS:
491 case SpvOpConvertSToF:
492 case SpvOpConvertUToF:
493 case SpvOpUConvert:
494 case SpvOpSConvert:
495 case SpvOpFConvert:
496 case SpvOpConvertPtrToU:
497 // TODO: case SpvOpConvertUToPtr:
498 case SpvOpPtrCastToGeneric:
499 // TODO: case SpvOpGenericCastToPtr:
500 case SpvOpBitcast:
501 // TODO: case SpvOpGenericCastToPtrExplicit:
502 case SpvOpSatConvertSToU:
503 case SpvOpSatConvertUToS:
504 case SpvOpVectorExtractDynamic:
505 case SpvOpCompositeConstruct:
506 case SpvOpCompositeExtract:
507 case SpvOpCopyObject:
508 case SpvOpTranspose:
509 case SpvOpSNegate:
510 case SpvOpFNegate:
511 case SpvOpNot:
512 case SpvOpIAdd:
513 case SpvOpFAdd:
514 case SpvOpISub:
515 case SpvOpFSub:
516 case SpvOpIMul:
517 case SpvOpFMul:
518 case SpvOpUDiv:
519 case SpvOpSDiv:
520 case SpvOpFDiv:
521 case SpvOpUMod:
522 case SpvOpSRem:
523 case SpvOpSMod:
524 case SpvOpVectorTimesScalar:
525 case SpvOpMatrixTimesScalar:
526 case SpvOpVectorTimesMatrix:
527 case SpvOpMatrixTimesVector:
528 case SpvOpMatrixTimesMatrix:
529 case SpvOpOuterProduct:
530 case SpvOpDot:
531 case SpvOpShiftRightLogical:
532 case SpvOpShiftRightArithmetic:
533 case SpvOpShiftLeftLogical:
534 case SpvOpBitwiseOr:
535 case SpvOpBitwiseXor:
536 case SpvOpBitwiseAnd:
537 case SpvOpAny:
538 case SpvOpAll:
539 case SpvOpIsNan:
540 case SpvOpIsInf:
541 case SpvOpIsFinite:
542 case SpvOpIsNormal:
543 case SpvOpSignBitSet:
544 case SpvOpLessOrGreater:
545 case SpvOpOrdered:
546 case SpvOpUnordered:
547 case SpvOpLogicalOr:
548 case SpvOpLogicalAnd:
549 case SpvOpSelect:
550 case SpvOpIEqual:
551 case SpvOpFOrdEqual:
552 case SpvOpFUnordEqual:
553 case SpvOpINotEqual:
554 case SpvOpFOrdNotEqual:
555 case SpvOpFUnordNotEqual:
556 case SpvOpULessThan:
557 case SpvOpSLessThan:
558 case SpvOpFOrdLessThan:
559 case SpvOpFUnordLessThan:
560 case SpvOpUGreaterThan:
561 case SpvOpSGreaterThan:
562 case SpvOpFOrdGreaterThan:
563 case SpvOpFUnordGreaterThan:
564 case SpvOpULessThanEqual:
565 case SpvOpSLessThanEqual:
566 case SpvOpFOrdLessThanEqual:
567 case SpvOpFUnordLessThanEqual:
568 case SpvOpUGreaterThanEqual:
569 case SpvOpSGreaterThanEqual:
570 case SpvOpFOrdGreaterThanEqual:
571 case SpvOpFUnordGreaterThanEqual:
572 case SpvOpDPdx:
573 case SpvOpDPdy:
574 case SpvOpFwidth:
575 case SpvOpDPdxFine:
576 case SpvOpDPdyFine:
577 case SpvOpFwidthFine:
578 case SpvOpDPdxCoarse:
579 case SpvOpDPdyCoarse:
580 case SpvOpFwidthCoarse:
581 case SpvOpReturnValue:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100582 return true;
583 default:
584 return false;
585 }
586}
587
Lei Zhangb36e7042015-10-28 13:40:52 -0400588int32_t spvOpcodeIsBasicTypeNullable(SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100589 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400590 case SpvOpTypeBool:
591 case SpvOpTypeInt:
592 case SpvOpTypeFloat:
593 case SpvOpTypePointer:
594 case SpvOpTypeEvent:
595 case SpvOpTypeDeviceEvent:
596 case SpvOpTypeReserveId:
597 case SpvOpTypeQueue:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100598 return true;
599 default:
600 return false;
601 }
602}
603
Lei Zhang1a0334e2015-11-02 09:41:20 -0500604int32_t spvInstructionIsInBasicBlock(const spv_instruction_t* pFirstInst,
605 const spv_instruction_t* pInst) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100606 while (pFirstInst != pInst) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400607 if (SpvOpFunction == pInst->opcode) break;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100608 pInst--;
609 }
Lei Zhangb36e7042015-10-28 13:40:52 -0400610 if (SpvOpFunction != pInst->opcode) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100611 return true;
612}
613
Lei Zhangb36e7042015-10-28 13:40:52 -0400614int32_t spvOpcodeIsValue(SpvOp opcode) {
Lei Zhang40056702015-09-11 14:31:27 -0400615 if (spvOpcodeIsPointer(opcode)) return true;
616 if (spvOpcodeIsConstant(opcode)) return true;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100617 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400618 case SpvOpLoad:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100619 // TODO: Other Opcode's resulting in a value
620 return true;
621 default:
622 return false;
623 }
624}
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400625
Lei Zhangb36e7042015-10-28 13:40:52 -0400626int32_t spvOpcodeGeneratesType(SpvOp op) {
Lei Zhang1a0334e2015-11-02 09:41:20 -0500627 switch (op) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400628 case SpvOpTypeVoid:
629 case SpvOpTypeBool:
630 case SpvOpTypeInt:
631 case SpvOpTypeFloat:
632 case SpvOpTypeVector:
633 case SpvOpTypeMatrix:
634 case SpvOpTypeImage:
635 case SpvOpTypeSampler:
636 case SpvOpTypeSampledImage:
637 case SpvOpTypeArray:
638 case SpvOpTypeRuntimeArray:
639 case SpvOpTypeStruct:
640 case SpvOpTypeOpaque:
641 case SpvOpTypePointer:
642 case SpvOpTypeFunction:
643 case SpvOpTypeEvent:
644 case SpvOpTypeDeviceEvent:
645 case SpvOpTypeReserveId:
646 case SpvOpTypeQueue:
647 case SpvOpTypePipe:
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400648 return true;
David Netoaef608c2015-11-02 14:59:02 -0500649 default:
650 // In particular, OpTypeForwardPointer does not generate a type,
651 // but declares a storage class for a pointer type generated
652 // by a different instruction.
653 break;
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400654 }
655 return 0;
656}