blob: f7e3259c53729244fb6b87bde8e156c58280771b [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"
35
David Neto78c3b432015-08-27 13:03:52 -040036namespace {
37
38// Descriptions of each opcode. Each entry describes the format of the
39// instruction that follows a particular opcode.
40//
41// Most fields are initialized statically by including an automatically
42// generated file.
43// The operandTypes fields are initialized during spvOpcodeInitialize().
44//
45// TODO(dneto): Some of the macros are quite unreadable. We could make
46// good use of constexpr functions, but some compilers don't support that yet.
47spv_opcode_desc_t opcodeTableEntries[] = {
Lei Zhang1a0334e2015-11-02 09:41:20 -050048#define EmptyList \
49 {}
50#define List(...) \
51 { __VA_ARGS__ }
Lei Zhangb36e7042015-10-28 13:40:52 -040052#define Capability(X) SPV_CAPABILITY_AS_MASK(SpvCapability##X)
Lei Zhang1a0334e2015-11-02 09:41:20 -050053#define Capability2(X, Y) Capability(X) | Capability(Y)
54#define SpvCapabilityNone \
55 0 // Needed so Capability(None) still expands to valid syntax.
David Neto201caf72015-11-04 17:38:17 -050056#define Instruction(Name, HasResult, HasType, NumLogicalOperands, \
57 NumCapabilities, CapabilityRequired, IsVariable, \
58 LogicalArgsList) \
59 {#Name, SpvOp##Name, (NumCapabilities) ? (CapabilityRequired) : 0, \
60 0, {}, /* Filled in later. Operand list, including \
61 result id and type id, if needed */ \
62 HasResult, HasType, LogicalArgsList},
David Neto78c3b432015-08-27 13:03:52 -040063#include "opcode.inc"
64#undef EmptyList
65#undef List
66#undef Capability
Dejan Mircevski205408b2015-09-30 16:42:34 -040067#undef Capability2
David Neto78c3b432015-08-27 13:03:52 -040068#undef CapabilityNone
69#undef Instruction
70};
71
72// Has the opcodeTableEntries table been fully elaborated?
73// That is, are the operandTypes fields initialized?
74bool opcodeTableInitialized = false;
75
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010076// Opcode API
77
David Neto78c3b432015-08-27 13:03:52 -040078// Converts the given operand class enum (from the SPIR-V document generation
David Neto0f166be2015-11-11 01:56:49 -050079// logic) to the operand type required by the parser. The SPV_OPERAND_TYPE_NONE
80// value indicates there is no current operand and no further operands.
David Neto78c3b432015-08-27 13:03:52 -040081// This only applies to logical operands.
Lei Zhangb36e7042015-10-28 13:40:52 -040082spv_operand_type_t convertOperandClassToType(SpvOp opcode,
83 OperandClass operandClass) {
David Neto78c3b432015-08-27 13:03:52 -040084 // The spec document generator uses OptionalOperandLiteral for several kinds
85 // of repeating values. Our parser needs more specific information about
86 // what is being repeated.
87 if (operandClass == OperandOptionalLiteral) {
Lei Zhang40056702015-09-11 14:31:27 -040088 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -040089 case SpvOpLoad:
90 case SpvOpStore:
91 case SpvOpCopyMemory:
92 case SpvOpCopyMemorySized:
David Neto3fca4cd2015-09-17 17:39:45 -040093 // Expect an optional mask. When the Aligned bit is set in the mask,
94 // we will later add the expectation of a literal number operand.
95 return SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS;
Lei Zhangb36e7042015-10-28 13:40:52 -040096 case SpvOpExecutionMode:
David Neto78c3b432015-08-27 13:03:52 -040097 return SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE;
98 default:
99 break;
100 }
Lei Zhangb41d1502015-09-14 15:22:23 -0400101 } else if (operandClass == OperandVariableLiterals) {
David Neto201caf72015-11-04 17:38:17 -0500102 if (opcode == SpvOpConstant || opcode == SpvOpSpecConstant) {
103 // The number type is determined by the type Id operand.
104 return SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER;
105 }
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:
David Neto0f166be2015-11-11 01:56:49 -0500118 if (opcode == SpvOpSpecConstantOp) {
119 // These are the operands to the specialization constant opcode.
120 // The assembler and binary parser set up the extra Id and literal
121 // arguments when processing the opcode operand. So don't add
122 // an operand type for them here.
123 return SPV_OPERAND_TYPE_NONE;
124 }
Lei Zhang1a0334e2015-11-02 09:41:20 -0500125 return SPV_OPERAND_TYPE_VARIABLE_ID;
David Neto561dc4e2015-09-25 14:23:29 -0400126 // The spec only uses OptionalLiteral for an optional literal number.
Lei Zhang1a0334e2015-11-02 09:41:20 -0500127 case OperandOptionalLiteral:
128 return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER;
129 case OperandOptionalLiteralString:
130 return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING;
David Neto561dc4e2015-09-25 14:23:29 -0400131 // This is only used for sequences of literal numbers.
Lei Zhang1a0334e2015-11-02 09:41:20 -0500132 case OperandVariableLiterals:
133 return SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER;
David Neto445ce442015-10-15 15:22:06 -0400134 case OperandLiteralNumber:
Lei Zhangb36e7042015-10-28 13:40:52 -0400135 if (opcode == SpvOpExtInst) {
David Neto445ce442015-10-15 15:22:06 -0400136 // We use a special operand type for the extension instruction number.
Lei Zhang1a0334e2015-11-02 09:41:20 -0500137 // For now, we assume there is only one LiteraNumber argument to
138 // OpExtInst, and it is the extension instruction argument.
David Neto445ce442015-10-15 15:22:06 -0400139 // See the ExtInst entry in opcode.inc
140 // TODO(dneto): Use a function to confirm the assumption, and to verify
141 // that the index into the operandClass is 1, as expected.
142 return SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER;
David Neto0f166be2015-11-11 01:56:49 -0500143 } else if (opcode == SpvOpSpecConstantOp) {
144 // Use a special operand type for the opcode operand, so we can
145 // use mnemonic names instead of the numbers. For example, the
146 // assembler should accept "IAdd" instead of the numeric value of
147 // SpvOpIAdd.
148 return SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER;
David Neto445ce442015-10-15 15:22:06 -0400149 }
150 return SPV_OPERAND_TYPE_LITERAL_INTEGER;
Lei Zhang1a0334e2015-11-02 09:41:20 -0500151 case OperandLiteralString:
152 return SPV_OPERAND_TYPE_LITERAL_STRING;
153 case OperandSource:
154 return SPV_OPERAND_TYPE_SOURCE_LANGUAGE;
155 case OperandExecutionModel:
156 return SPV_OPERAND_TYPE_EXECUTION_MODEL;
157 case OperandAddressing:
158 return SPV_OPERAND_TYPE_ADDRESSING_MODEL;
159 case OperandMemory:
160 return SPV_OPERAND_TYPE_MEMORY_MODEL;
161 case OperandExecutionMode:
162 return SPV_OPERAND_TYPE_EXECUTION_MODE;
163 case OperandStorage:
164 return SPV_OPERAND_TYPE_STORAGE_CLASS;
165 case OperandDimensionality:
166 return SPV_OPERAND_TYPE_DIMENSIONALITY;
167 case OperandSamplerAddressingMode:
168 return SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE;
169 case OperandSamplerFilterMode:
170 return SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE;
171 case OperandSamplerImageFormat:
172 return SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT;
David Neto7cefb232015-09-28 15:33:49 -0400173 case OperandImageChannelOrder:
174 // This is only used to describe the value generated by OpImageQueryOrder.
175 // It is not used as an operand.
176 break;
177 case OperandImageChannelDataType:
Lei Zhang1a0334e2015-11-02 09:41:20 -0500178 // This is only used to describe the value generated by
179 // OpImageQueryFormat. It is not used as an operand.
David Neto7cefb232015-09-28 15:33:49 -0400180 break;
181 case OperandImageOperands:
Dejan Mircevskif8e091a2015-10-13 14:41:31 -0400182 // This is not used in opcode.inc. It only exists to generate the
183 // corresponding spec section. In parsing, image operands meld into the
184 // OperandOptionalImage case.
David Neto7cefb232015-09-28 15:33:49 -0400185 break;
Lei Zhang1a0334e2015-11-02 09:41:20 -0500186 case OperandFPFastMath:
187 return SPV_OPERAND_TYPE_FP_FAST_MATH_MODE;
188 case OperandFPRoundingMode:
189 return SPV_OPERAND_TYPE_FP_ROUNDING_MODE;
190 case OperandLinkageType:
191 return SPV_OPERAND_TYPE_LINKAGE_TYPE;
192 case OperandAccessQualifier:
193 return SPV_OPERAND_TYPE_ACCESS_QUALIFIER;
194 case OperandFuncParamAttr:
195 return SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE;
196 case OperandDecoration:
197 return SPV_OPERAND_TYPE_DECORATION;
198 case OperandBuiltIn:
199 return SPV_OPERAND_TYPE_BUILT_IN;
200 case OperandSelect:
201 return SPV_OPERAND_TYPE_SELECTION_CONTROL;
202 case OperandLoop:
203 return SPV_OPERAND_TYPE_LOOP_CONTROL;
204 case OperandFunction:
205 return SPV_OPERAND_TYPE_FUNCTION_CONTROL;
206 case OperandMemorySemantics:
207 return SPV_OPERAND_TYPE_MEMORY_SEMANTICS;
David Neto78c3b432015-08-27 13:03:52 -0400208 case OperandMemoryAccess:
David Neto7cefb232015-09-28 15:33:49 -0400209 // This case does not occur in the table for SPIR-V 0.99 Rev 32.
David Neto3fca4cd2015-09-17 17:39:45 -0400210 // We expect that it will become SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
David Neto78c3b432015-08-27 13:03:52 -0400211 // and we can remove the special casing above for memory operation
212 // instructions.
213 break;
Lei Zhang1a0334e2015-11-02 09:41:20 -0500214 case OperandScope:
215 return SPV_OPERAND_TYPE_EXECUTION_SCOPE;
216 case OperandGroupOperation:
217 return SPV_OPERAND_TYPE_GROUP_OPERATION;
218 case OperandKernelEnqueueFlags:
219 return SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS;
220 case OperandKernelProfilingInfo:
221 return SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO;
222 case OperandCapability:
223 return SPV_OPERAND_TYPE_CAPABILITY;
David Neto78c3b432015-08-27 13:03:52 -0400224
225 // Used by GroupMemberDecorate
Lei Zhang1a0334e2015-11-02 09:41:20 -0500226 case OperandVariableIdLiteral:
227 return SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER;
David Neto78c3b432015-08-27 13:03:52 -0400228
229 // Used by Switch
Lei Zhang1a0334e2015-11-02 09:41:20 -0500230 case OperandVariableLiteralId:
231 return SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID;
David Neto78c3b432015-08-27 13:03:52 -0400232
233 // These exceptional cases shouldn't occur.
234 case OperandCount:
235 default:
236 break;
237 }
238 assert(0 && "Unexpected operand class");
239 return SPV_OPERAND_TYPE_NONE;
240}
241
Lei Zhanga94701d2015-09-14 10:05:37 -0400242} // anonymous namespace
David Neto78c3b432015-08-27 13:03:52 -0400243
244// Finish populating the opcodeTableEntries array.
245void spvOpcodeTableInitialize() {
246 // Compute the operandTypes field for each entry.
Lei Zhang1a0334e2015-11-02 09:41:20 -0500247 for (auto& opcode : opcodeTableEntries) {
David Neto78c3b432015-08-27 13:03:52 -0400248 opcode.numTypes = 0;
249 // Type ID always comes first, if present.
250 if (opcode.hasType)
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400251 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_TYPE_ID;
David Neto78c3b432015-08-27 13:03:52 -0400252 // Result ID always comes next, if present
253 if (opcode.hasResult)
254 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_RESULT_ID;
Lei Zhanga94701d2015-09-14 10:05:37 -0400255 const uint16_t maxNumOperands =
256 sizeof(opcode.operandTypes) / sizeof(opcode.operandTypes[0]);
257 const uint16_t maxNumClasses =
258 sizeof(opcode.operandClass) / sizeof(opcode.operandClass[0]);
259 for (uint16_t classIndex = 0;
260 opcode.numTypes < maxNumOperands && classIndex < maxNumClasses;
261 classIndex++) {
David Neto78c3b432015-08-27 13:03:52 -0400262 const OperandClass operandClass = opcode.operandClass[classIndex];
David Neto0f166be2015-11-11 01:56:49 -0500263 const auto operandType =
Lei Zhanga94701d2015-09-14 10:05:37 -0400264 convertOperandClassToType(opcode.opcode, operandClass);
David Neto0f166be2015-11-11 01:56:49 -0500265 opcode.operandTypes[opcode.numTypes++] = operandType;
David Neto78c3b432015-08-27 13:03:52 -0400266 // The OperandNone value is not explicitly represented in the .inc file.
267 // However, it is the zero value, and is created via implicit value
David Neto0f166be2015-11-11 01:56:49 -0500268 // initialization. It converts to SPV_OPERAND_TYPE_NONE.
269 // The SPV_OPERAND_TYPE_NONE operand type indicates no current or futher
270 // operands.
271 if (operandType == SPV_OPERAND_TYPE_NONE) {
David Neto78c3b432015-08-27 13:03:52 -0400272 opcode.numTypes--;
273 break;
274 }
275 }
David Neto0f166be2015-11-11 01:56:49 -0500276
David Neto78c3b432015-08-27 13:03:52 -0400277 // We should have written the terminating SPV_OPERAND_TYPE_NONE entry, but
278 // also without overflowing.
Lei Zhanga94701d2015-09-14 10:05:37 -0400279 assert((opcode.numTypes < maxNumOperands) &&
280 "Operand class list is too long. Expand "
281 "spv_opcode_desc_t.operandClass");
David Neto78c3b432015-08-27 13:03:52 -0400282 }
283 opcodeTableInitialized = true;
284}
285
Lei Zhang1a0334e2015-11-02 09:41:20 -0500286const char* spvGeneratorStr(uint32_t generator) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100287 switch (generator) {
288 case SPV_GENERATOR_KHRONOS:
289 return "Khronos";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100290 case SPV_GENERATOR_LUNARG:
291 return "LunarG";
David Neto1780fc42015-10-26 15:43:12 -0400292 case SPV_GENERATOR_VALVE:
293 return "Valve";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100294 case SPV_GENERATOR_CODEPLAY:
295 return "Codeplay Software Ltd.";
David Neto1780fc42015-10-26 15:43:12 -0400296 case SPV_GENERATOR_NVIDIA:
297 return "NVIDIA";
298 case SPV_GENERATOR_ARM:
299 return "ARM";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100300 default:
301 return "Unknown";
302 }
303}
304
Lei Zhangb36e7042015-10-28 13:40:52 -0400305uint32_t spvOpcodeMake(uint16_t wordCount, SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100306 return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
307}
308
Lei Zhang1a0334e2015-11-02 09:41:20 -0500309void spvOpcodeSplit(const uint32_t word, uint16_t* pWordCount, SpvOp* pOpcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100310 if (pWordCount) {
311 *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
312 }
313 if (pOpcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400314 *pOpcode = (SpvOp)(0x0000ffff & word);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100315 }
316}
317
Lei Zhang1a0334e2015-11-02 09:41:20 -0500318spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable) {
Lei Zhang40056702015-09-11 14:31:27 -0400319 if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100320
David Neto78c3b432015-08-27 13:03:52 -0400321 static spv_opcode_table_t table = {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100322 sizeof(opcodeTableEntries) / sizeof(spv_opcode_desc_t),
323 opcodeTableEntries};
324
David Neto78c3b432015-08-27 13:03:52 -0400325 // TODO(dneto): Consider thread safety of initialization.
326 // That is, ordering effects of the flag vs. the table updates.
Lei Zhang40056702015-09-11 14:31:27 -0400327 if (!opcodeTableInitialized) spvOpcodeTableInitialize();
David Neto78c3b432015-08-27 13:03:52 -0400328
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100329 *pInstTable = &table;
330
331 return SPV_SUCCESS;
332}
333
334spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500335 const char* name,
336 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400337 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
338 if (!table) return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100339
340 // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
341 // preferable but the table requires sorting on the Opcode name, but it's
342 // static
343 // const initialized and matches the order of the spec.
344 const size_t nameLength = strlen(name);
345 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
346 if (nameLength == strlen(table->entries[opcodeIndex].name) &&
347 !strncmp(name, table->entries[opcodeIndex].name, nameLength)) {
348 // NOTE: Found out Opcode!
349 *pEntry = &table->entries[opcodeIndex];
350 return SPV_SUCCESS;
351 }
352 }
353
354 return SPV_ERROR_INVALID_LOOKUP;
355}
356
357spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
Lei Zhangb36e7042015-10-28 13:40:52 -0400358 const SpvOp opcode,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500359 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400360 if (!table) return SPV_ERROR_INVALID_TABLE;
361 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100362
363 // TODO: As above this lookup is not optimal.
364 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
365 if (opcode == table->entries[opcodeIndex].opcode) {
366 // NOTE: Found the Opcode!
367 *pEntry = &table->entries[opcodeIndex];
368 return SPV_SUCCESS;
369 }
370 }
371
372 return SPV_ERROR_INVALID_LOOKUP;
373}
374
Lei Zhangdfc50082015-08-21 11:50:55 -0400375int16_t spvOpcodeResultIdIndex(spv_opcode_desc entry) {
David Neto78c3b432015-08-27 13:03:52 -0400376 for (int16_t i = 0; i < entry->numTypes; ++i) {
Lei Zhangdfc50082015-08-21 11:50:55 -0400377 if (SPV_OPERAND_TYPE_RESULT_ID == entry->operandTypes[i]) return i;
378 }
379 return SPV_OPERAND_INVALID_RESULT_ID_INDEX;
380}
381
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100382int32_t spvOpcodeRequiresCapabilities(spv_opcode_desc entry) {
David Neto9db3a532015-10-07 16:58:38 -0400383 return entry->capabilities != 0;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100384}
385
Lei Zhang1a0334e2015-11-02 09:41:20 -0500386void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100387 const uint16_t wordCount, const spv_endianness_t endian,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500388 spv_instruction_t* pInst) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100389 pInst->opcode = opcode;
David Netob5dc8fc2015-10-06 16:22:00 -0400390 pInst->words.resize(wordCount);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100391 for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
392 pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
393 if (!wordIndex) {
394 uint16_t thisWordCount;
Lei Zhangb36e7042015-10-28 13:40:52 -0400395 SpvOp thisOpcode;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100396 spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
397 assert(opcode == thisOpcode && wordCount == thisWordCount &&
398 "Endianness failed!");
399 }
400 }
401}
402
Lei Zhang1a0334e2015-11-02 09:41:20 -0500403const char* spvOpcodeString(const SpvOp opcode) {
David Neto201caf72015-11-04 17:38:17 -0500404// Use the syntax table so it's sure to be complete.
David Neto1bcd3d12015-11-02 16:03:12 -0500405#define Instruction(Name, ...) \
406 case SpvOp##Name: \
407 return #Name;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100408 switch (opcode) {
David Neto1bcd3d12015-11-02 16:03:12 -0500409#include "opcode.inc"
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100410 default:
411 assert(0 && "Unreachable!");
412 }
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100413 return "unknown";
David Neto1bcd3d12015-11-02 16:03:12 -0500414#undef Instruction
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100415}
416
Lei Zhangb36e7042015-10-28 13:40:52 -0400417int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100418 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400419 case SpvOpTypeInt:
420 case SpvOpTypeFloat:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100421 return true;
422 default:
423 return false;
424 }
425}
426
Lei Zhangb36e7042015-10-28 13:40:52 -0400427int32_t spvOpcodeIsConstant(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100428 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400429 case SpvOpConstantTrue:
430 case SpvOpConstantFalse:
431 case SpvOpConstant:
432 case SpvOpConstantComposite:
433 case SpvOpConstantSampler:
434 // case SpvOpConstantNull:
435 case SpvOpConstantNull:
436 case SpvOpSpecConstantTrue:
437 case SpvOpSpecConstantFalse:
438 case SpvOpSpecConstant:
439 case SpvOpSpecConstantComposite:
440 // case SpvOpSpecConstantOp:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100441 return true;
442 default:
443 return false;
444 }
445}
446
Lei Zhangb36e7042015-10-28 13:40:52 -0400447int32_t spvOpcodeIsComposite(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100448 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400449 case SpvOpTypeVector:
450 case SpvOpTypeMatrix:
451 case SpvOpTypeArray:
452 case SpvOpTypeStruct:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100453 return true;
454 default:
455 return false;
456 }
457}
458
Lei Zhang1a0334e2015-11-02 09:41:20 -0500459int32_t spvOpcodeAreTypesEqual(const spv_instruction_t* pTypeInst0,
460 const spv_instruction_t* pTypeInst1) {
Lei Zhang40056702015-09-11 14:31:27 -0400461 if (pTypeInst0->opcode != pTypeInst1->opcode) return false;
462 if (pTypeInst0->words[1] != pTypeInst1->words[1]) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100463 return true;
464}
465
Lei Zhangb36e7042015-10-28 13:40:52 -0400466int32_t spvOpcodeIsPointer(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100467 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400468 case SpvOpVariable:
469 case SpvOpAccessChain:
470 case SpvOpInBoundsAccessChain:
471 case SpvOpFunctionParameter:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100472 return true;
473 default:
474 return false;
475 }
476}
477
Lei Zhangb36e7042015-10-28 13:40:52 -0400478int32_t spvOpcodeIsObject(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100479 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400480 case SpvOpConstantTrue:
481 case SpvOpConstantFalse:
482 case SpvOpConstant:
483 case SpvOpConstantComposite:
484 // TODO: case SpvOpConstantSampler:
485 case SpvOpConstantNull:
486 case SpvOpSpecConstantTrue:
487 case SpvOpSpecConstantFalse:
488 case SpvOpSpecConstant:
489 case SpvOpSpecConstantComposite:
490 // TODO: case SpvOpSpecConstantOp:
491 case SpvOpVariable:
492 case SpvOpAccessChain:
493 case SpvOpInBoundsAccessChain:
494 case SpvOpConvertFToU:
495 case SpvOpConvertFToS:
496 case SpvOpConvertSToF:
497 case SpvOpConvertUToF:
498 case SpvOpUConvert:
499 case SpvOpSConvert:
500 case SpvOpFConvert:
501 case SpvOpConvertPtrToU:
502 // TODO: case SpvOpConvertUToPtr:
503 case SpvOpPtrCastToGeneric:
504 // TODO: case SpvOpGenericCastToPtr:
505 case SpvOpBitcast:
506 // TODO: case SpvOpGenericCastToPtrExplicit:
507 case SpvOpSatConvertSToU:
508 case SpvOpSatConvertUToS:
509 case SpvOpVectorExtractDynamic:
510 case SpvOpCompositeConstruct:
511 case SpvOpCompositeExtract:
512 case SpvOpCopyObject:
513 case SpvOpTranspose:
514 case SpvOpSNegate:
515 case SpvOpFNegate:
516 case SpvOpNot:
517 case SpvOpIAdd:
518 case SpvOpFAdd:
519 case SpvOpISub:
520 case SpvOpFSub:
521 case SpvOpIMul:
522 case SpvOpFMul:
523 case SpvOpUDiv:
524 case SpvOpSDiv:
525 case SpvOpFDiv:
526 case SpvOpUMod:
527 case SpvOpSRem:
528 case SpvOpSMod:
529 case SpvOpVectorTimesScalar:
530 case SpvOpMatrixTimesScalar:
531 case SpvOpVectorTimesMatrix:
532 case SpvOpMatrixTimesVector:
533 case SpvOpMatrixTimesMatrix:
534 case SpvOpOuterProduct:
535 case SpvOpDot:
536 case SpvOpShiftRightLogical:
537 case SpvOpShiftRightArithmetic:
538 case SpvOpShiftLeftLogical:
539 case SpvOpBitwiseOr:
540 case SpvOpBitwiseXor:
541 case SpvOpBitwiseAnd:
542 case SpvOpAny:
543 case SpvOpAll:
544 case SpvOpIsNan:
545 case SpvOpIsInf:
546 case SpvOpIsFinite:
547 case SpvOpIsNormal:
548 case SpvOpSignBitSet:
549 case SpvOpLessOrGreater:
550 case SpvOpOrdered:
551 case SpvOpUnordered:
552 case SpvOpLogicalOr:
553 case SpvOpLogicalAnd:
554 case SpvOpSelect:
555 case SpvOpIEqual:
556 case SpvOpFOrdEqual:
557 case SpvOpFUnordEqual:
558 case SpvOpINotEqual:
559 case SpvOpFOrdNotEqual:
560 case SpvOpFUnordNotEqual:
561 case SpvOpULessThan:
562 case SpvOpSLessThan:
563 case SpvOpFOrdLessThan:
564 case SpvOpFUnordLessThan:
565 case SpvOpUGreaterThan:
566 case SpvOpSGreaterThan:
567 case SpvOpFOrdGreaterThan:
568 case SpvOpFUnordGreaterThan:
569 case SpvOpULessThanEqual:
570 case SpvOpSLessThanEqual:
571 case SpvOpFOrdLessThanEqual:
572 case SpvOpFUnordLessThanEqual:
573 case SpvOpUGreaterThanEqual:
574 case SpvOpSGreaterThanEqual:
575 case SpvOpFOrdGreaterThanEqual:
576 case SpvOpFUnordGreaterThanEqual:
577 case SpvOpDPdx:
578 case SpvOpDPdy:
579 case SpvOpFwidth:
580 case SpvOpDPdxFine:
581 case SpvOpDPdyFine:
582 case SpvOpFwidthFine:
583 case SpvOpDPdxCoarse:
584 case SpvOpDPdyCoarse:
585 case SpvOpFwidthCoarse:
586 case SpvOpReturnValue:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100587 return true;
588 default:
589 return false;
590 }
591}
592
Lei Zhangb36e7042015-10-28 13:40:52 -0400593int32_t spvOpcodeIsBasicTypeNullable(SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100594 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400595 case SpvOpTypeBool:
596 case SpvOpTypeInt:
597 case SpvOpTypeFloat:
598 case SpvOpTypePointer:
599 case SpvOpTypeEvent:
600 case SpvOpTypeDeviceEvent:
601 case SpvOpTypeReserveId:
602 case SpvOpTypeQueue:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100603 return true;
604 default:
605 return false;
606 }
607}
608
Lei Zhang1a0334e2015-11-02 09:41:20 -0500609int32_t spvInstructionIsInBasicBlock(const spv_instruction_t* pFirstInst,
610 const spv_instruction_t* pInst) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100611 while (pFirstInst != pInst) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400612 if (SpvOpFunction == pInst->opcode) break;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100613 pInst--;
614 }
Lei Zhangb36e7042015-10-28 13:40:52 -0400615 if (SpvOpFunction != pInst->opcode) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100616 return true;
617}
618
Lei Zhangb36e7042015-10-28 13:40:52 -0400619int32_t spvOpcodeIsValue(SpvOp opcode) {
Lei Zhang40056702015-09-11 14:31:27 -0400620 if (spvOpcodeIsPointer(opcode)) return true;
621 if (spvOpcodeIsConstant(opcode)) return true;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100622 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400623 case SpvOpLoad:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100624 // TODO: Other Opcode's resulting in a value
625 return true;
626 default:
627 return false;
628 }
629}
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400630
Lei Zhangb36e7042015-10-28 13:40:52 -0400631int32_t spvOpcodeGeneratesType(SpvOp op) {
Lei Zhang1a0334e2015-11-02 09:41:20 -0500632 switch (op) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400633 case SpvOpTypeVoid:
634 case SpvOpTypeBool:
635 case SpvOpTypeInt:
636 case SpvOpTypeFloat:
637 case SpvOpTypeVector:
638 case SpvOpTypeMatrix:
639 case SpvOpTypeImage:
640 case SpvOpTypeSampler:
641 case SpvOpTypeSampledImage:
642 case SpvOpTypeArray:
643 case SpvOpTypeRuntimeArray:
644 case SpvOpTypeStruct:
645 case SpvOpTypeOpaque:
646 case SpvOpTypePointer:
647 case SpvOpTypeFunction:
648 case SpvOpTypeEvent:
649 case SpvOpTypeDeviceEvent:
650 case SpvOpTypeReserveId:
651 case SpvOpTypeQueue:
652 case SpvOpTypePipe:
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400653 return true;
David Netoaef608c2015-11-02 14:59:02 -0500654 default:
655 // In particular, OpTypeForwardPointer does not generate a type,
656 // but declares a storage class for a pointer type generated
657 // by a different instruction.
658 break;
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400659 }
660 return 0;
661}