blob: 70f1ad72b8f35ab03ddef12c6af2931a43661bb3 [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>
28#include "binary.h"
David Netob5dc8fc2015-10-06 16:22:00 -040029#include "instruction.h"
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010030#include "opcode.h"
31
32#include <assert.h>
33#include <string.h>
34
David Neto78c3b432015-08-27 13:03:52 -040035namespace {
36
37// Descriptions of each opcode. Each entry describes the format of the
38// instruction that follows a particular opcode.
39//
40// Most fields are initialized statically by including an automatically
41// generated file.
42// The operandTypes fields are initialized during spvOpcodeInitialize().
43//
44// TODO(dneto): Some of the macros are quite unreadable. We could make
45// good use of constexpr functions, but some compilers don't support that yet.
46spv_opcode_desc_t opcodeTableEntries[] = {
47#define EmptyList {}
48#define List(...) {__VA_ARGS__}
Dejan Mircevski205408b2015-09-30 16:42:34 -040049#define Capability(X) SPV_CAPABILITY_AS_MASK(Capability##X)
50#define Capability2(X,Y) Capability(X)|Capability(Y)
51#define CapabilityNone 0 // Needed so Capability(None) still expands to valid syntax.
David Neto78c3b432015-08-27 13:03:52 -040052#define Instruction(Name,HasResult,HasType,NumLogicalOperands,NumCapabilities,CapabilityRequired,IsVariable,LogicalArgsList) \
53 { #Name, \
54 Op##Name, \
Dejan Mircevski205408b2015-09-30 16:42:34 -040055 (NumCapabilities) ? (CapabilityRequired) : 0, \
David Neto78c3b432015-08-27 13:03:52 -040056 0, {}, /* Filled in later. Operand list, including result id and type id, if needed */ \
57 HasResult, \
58 HasType, \
59 LogicalArgsList },
60#include "opcode.inc"
61#undef EmptyList
62#undef List
63#undef Capability
Dejan Mircevski205408b2015-09-30 16:42:34 -040064#undef Capability2
David Neto78c3b432015-08-27 13:03:52 -040065#undef CapabilityNone
66#undef Instruction
67};
68
69// Has the opcodeTableEntries table been fully elaborated?
70// That is, are the operandTypes fields initialized?
71bool opcodeTableInitialized = false;
72
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010073// Opcode API
74
David Neto78c3b432015-08-27 13:03:52 -040075// Converts the given operand class enum (from the SPIR-V document generation
76// logic) to the operand type required by the parser.
77// This only applies to logical operands.
Lei Zhang40056702015-09-11 14:31:27 -040078spv_operand_type_t convertOperandClassToType(spv::Op opcode,
79 spv::OperandClass operandClass) {
David Neto78c3b432015-08-27 13:03:52 -040080 // The spec document generator uses OptionalOperandLiteral for several kinds
81 // of repeating values. Our parser needs more specific information about
82 // what is being repeated.
83 if (operandClass == OperandOptionalLiteral) {
Lei Zhang40056702015-09-11 14:31:27 -040084 switch (opcode) {
David Neto78c3b432015-08-27 13:03:52 -040085 case spv::OpLoad:
86 case spv::OpStore:
87 case spv::OpCopyMemory:
88 case spv::OpCopyMemorySized:
David Neto3fca4cd2015-09-17 17:39:45 -040089 // Expect an optional mask. When the Aligned bit is set in the mask,
90 // we will later add the expectation of a literal number operand.
91 return SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS;
David Neto78c3b432015-08-27 13:03:52 -040092 case spv::OpExecutionMode:
93 return SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE;
94 default:
95 break;
96 }
Lei Zhangb41d1502015-09-14 15:22:23 -040097 } else if (operandClass == OperandVariableLiterals) {
98 if (opcode == spv::OpConstant || opcode == spv::OpSpecConstant)
99 return SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER;
David Neto78c3b432015-08-27 13:03:52 -0400100 }
101
102 switch(operandClass) {
103 case OperandNone: return SPV_OPERAND_TYPE_NONE;
104 case OperandId: return SPV_OPERAND_TYPE_ID;
105 case OperandOptionalId: return SPV_OPERAND_TYPE_OPTIONAL_ID;
David Neto561dc4e2015-09-25 14:23:29 -0400106 case OperandOptionalImage: return SPV_OPERAND_TYPE_OPTIONAL_IMAGE;
David Neto78c3b432015-08-27 13:03:52 -0400107 case OperandVariableIds: return SPV_OPERAND_TYPE_VARIABLE_ID;
David Neto561dc4e2015-09-25 14:23:29 -0400108 // The spec only uses OptionalLiteral for an optional literal number.
109 case OperandOptionalLiteral: return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER;
David Neto78c3b432015-08-27 13:03:52 -0400110 case OperandOptionalLiteralString: return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING;
David Neto561dc4e2015-09-25 14:23:29 -0400111 // This is only used for sequences of literal numbers.
112 case OperandVariableLiterals: return SPV_OPERAND_TYPE_VARIABLE_LITERAL_NUMBER;
David Neto78c3b432015-08-27 13:03:52 -0400113 case OperandLiteralNumber: return SPV_OPERAND_TYPE_LITERAL_NUMBER;
114 case OperandLiteralString: return SPV_OPERAND_TYPE_LITERAL_STRING;
115 case OperandSource: return SPV_OPERAND_TYPE_SOURCE_LANGUAGE;
116 case OperandExecutionModel: return SPV_OPERAND_TYPE_EXECUTION_MODEL;
117 case OperandAddressing: return SPV_OPERAND_TYPE_ADDRESSING_MODEL;
118 case OperandMemory: return SPV_OPERAND_TYPE_MEMORY_MODEL;
119 case OperandExecutionMode: return SPV_OPERAND_TYPE_EXECUTION_MODE;
120 case OperandStorage: return SPV_OPERAND_TYPE_STORAGE_CLASS;
121 case OperandDimensionality: return SPV_OPERAND_TYPE_DIMENSIONALITY;
122 case OperandSamplerAddressingMode: return SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE;
123 case OperandSamplerFilterMode: return SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE;
David Netob30a0c52015-09-16 15:56:43 -0400124 case OperandSamplerImageFormat: return SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT;
David Neto7cefb232015-09-28 15:33:49 -0400125 case OperandImageChannelOrder:
126 // This is only used to describe the value generated by OpImageQueryOrder.
127 // It is not used as an operand.
128 break;
129 case OperandImageChannelDataType:
130 // This is only used to describe the value generated by OpImageQueryFormat.
131 // It is not used as an operand.
132 break;
133 case OperandImageOperands:
134 // This is not used. It's only an artifact of spec generation.
135 break;
David Neto78c3b432015-08-27 13:03:52 -0400136 case OperandFPFastMath: return SPV_OPERAND_TYPE_FP_FAST_MATH_MODE;
137 case OperandFPRoundingMode: return SPV_OPERAND_TYPE_FP_ROUNDING_MODE;
138 case OperandLinkageType: return SPV_OPERAND_TYPE_LINKAGE_TYPE;
139 case OperandAccessQualifier: return SPV_OPERAND_TYPE_ACCESS_QUALIFIER;
140 case OperandFuncParamAttr: return SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE;
141 case OperandDecoration: return SPV_OPERAND_TYPE_DECORATION;
142 case OperandBuiltIn: return SPV_OPERAND_TYPE_BUILT_IN;
143 case OperandSelect: return SPV_OPERAND_TYPE_SELECTION_CONTROL;
144 case OperandLoop: return SPV_OPERAND_TYPE_LOOP_CONTROL;
145 case OperandFunction: return SPV_OPERAND_TYPE_FUNCTION_CONTROL;
146 case OperandMemorySemantics: return SPV_OPERAND_TYPE_MEMORY_SEMANTICS;
147 case OperandMemoryAccess:
David Neto7cefb232015-09-28 15:33:49 -0400148 // This case does not occur in the table for SPIR-V 0.99 Rev 32.
David Neto3fca4cd2015-09-17 17:39:45 -0400149 // We expect that it will become SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
David Neto78c3b432015-08-27 13:03:52 -0400150 // and we can remove the special casing above for memory operation
151 // instructions.
152 break;
153 case OperandScope: return SPV_OPERAND_TYPE_EXECUTION_SCOPE;
154 case OperandGroupOperation: return SPV_OPERAND_TYPE_GROUP_OPERATION;
155 case OperandKernelEnqueueFlags: return SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS;
156 case OperandKernelProfilingInfo: return SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO;
157 case OperandCapability: return SPV_OPERAND_TYPE_CAPABILITY;
158
159 // Used by GroupMemberDecorate
David Neto561dc4e2015-09-25 14:23:29 -0400160 case OperandVariableIdLiteral: return SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_NUMBER;
David Neto78c3b432015-08-27 13:03:52 -0400161
162 // Used by Switch
David Neto561dc4e2015-09-25 14:23:29 -0400163 case OperandVariableLiteralId: return SPV_OPERAND_TYPE_VARIABLE_LITERAL_NUMBER_ID;
David Neto78c3b432015-08-27 13:03:52 -0400164
165 // These exceptional cases shouldn't occur.
166 case OperandCount:
167 default:
168 break;
169 }
170 assert(0 && "Unexpected operand class");
171 return SPV_OPERAND_TYPE_NONE;
172}
173
Lei Zhanga94701d2015-09-14 10:05:37 -0400174} // anonymous namespace
David Neto78c3b432015-08-27 13:03:52 -0400175
176// Finish populating the opcodeTableEntries array.
177void spvOpcodeTableInitialize() {
178 // Compute the operandTypes field for each entry.
Lei Zhanga94701d2015-09-14 10:05:37 -0400179 for (auto &opcode : opcodeTableEntries) {
David Neto78c3b432015-08-27 13:03:52 -0400180 opcode.numTypes = 0;
181 // Type ID always comes first, if present.
182 if (opcode.hasType)
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400183 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_TYPE_ID;
David Neto78c3b432015-08-27 13:03:52 -0400184 // Result ID always comes next, if present
185 if (opcode.hasResult)
186 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_RESULT_ID;
Lei Zhanga94701d2015-09-14 10:05:37 -0400187 const uint16_t maxNumOperands =
188 sizeof(opcode.operandTypes) / sizeof(opcode.operandTypes[0]);
189 const uint16_t maxNumClasses =
190 sizeof(opcode.operandClass) / sizeof(opcode.operandClass[0]);
191 for (uint16_t classIndex = 0;
192 opcode.numTypes < maxNumOperands && classIndex < maxNumClasses;
193 classIndex++) {
David Neto78c3b432015-08-27 13:03:52 -0400194 const OperandClass operandClass = opcode.operandClass[classIndex];
Lei Zhanga94701d2015-09-14 10:05:37 -0400195 opcode.operandTypes[opcode.numTypes++] =
196 convertOperandClassToType(opcode.opcode, operandClass);
David Neto78c3b432015-08-27 13:03:52 -0400197 // The OperandNone value is not explicitly represented in the .inc file.
198 // However, it is the zero value, and is created via implicit value
199 // initialization.
200 if (operandClass == OperandNone) {
201 opcode.numTypes--;
202 break;
203 }
204 }
205 // We should have written the terminating SPV_OPERAND_TYPE_NONE entry, but
206 // also without overflowing.
Lei Zhanga94701d2015-09-14 10:05:37 -0400207 assert((opcode.numTypes < maxNumOperands) &&
208 "Operand class list is too long. Expand "
209 "spv_opcode_desc_t.operandClass");
David Neto78c3b432015-08-27 13:03:52 -0400210 }
211 opcodeTableInitialized = true;
212}
213
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100214const char *spvGeneratorStr(uint32_t generator) {
215 switch (generator) {
216 case SPV_GENERATOR_KHRONOS:
217 return "Khronos";
218 case SPV_GENERATOR_VALVE:
219 return "Valve";
220 case SPV_GENERATOR_LUNARG:
221 return "LunarG";
222 case SPV_GENERATOR_CODEPLAY:
223 return "Codeplay Software Ltd.";
224 default:
225 return "Unknown";
226 }
227}
228
229uint32_t spvOpcodeMake(uint16_t wordCount, Op opcode) {
230 return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
231}
232
233void spvOpcodeSplit(const uint32_t word, uint16_t *pWordCount, Op *pOpcode) {
234 if (pWordCount) {
235 *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
236 }
237 if (pOpcode) {
238 *pOpcode = (Op)(0x0000ffff & word);
239 }
240}
241
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100242spv_result_t spvOpcodeTableGet(spv_opcode_table *pInstTable) {
Lei Zhang40056702015-09-11 14:31:27 -0400243 if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100244
David Neto78c3b432015-08-27 13:03:52 -0400245 static spv_opcode_table_t table = {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100246 sizeof(opcodeTableEntries) / sizeof(spv_opcode_desc_t),
247 opcodeTableEntries};
248
David Neto78c3b432015-08-27 13:03:52 -0400249 // TODO(dneto): Consider thread safety of initialization.
250 // That is, ordering effects of the flag vs. the table updates.
Lei Zhang40056702015-09-11 14:31:27 -0400251 if (!opcodeTableInitialized) spvOpcodeTableInitialize();
David Neto78c3b432015-08-27 13:03:52 -0400252
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100253 *pInstTable = &table;
254
255 return SPV_SUCCESS;
256}
257
258spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
259 const char *name,
260 spv_opcode_desc *pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400261 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
262 if (!table) return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100263
264 // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
265 // preferable but the table requires sorting on the Opcode name, but it's
266 // static
267 // const initialized and matches the order of the spec.
268 const size_t nameLength = strlen(name);
269 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
270 if (nameLength == strlen(table->entries[opcodeIndex].name) &&
271 !strncmp(name, table->entries[opcodeIndex].name, nameLength)) {
272 // NOTE: Found out Opcode!
273 *pEntry = &table->entries[opcodeIndex];
274 return SPV_SUCCESS;
275 }
276 }
277
278 return SPV_ERROR_INVALID_LOOKUP;
279}
280
281spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
282 const Op opcode,
283 spv_opcode_desc *pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400284 if (!table) return SPV_ERROR_INVALID_TABLE;
285 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100286
287 // TODO: As above this lookup is not optimal.
288 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
289 if (opcode == table->entries[opcodeIndex].opcode) {
290 // NOTE: Found the Opcode!
291 *pEntry = &table->entries[opcodeIndex];
292 return SPV_SUCCESS;
293 }
294 }
295
296 return SPV_ERROR_INVALID_LOOKUP;
297}
298
Lei Zhangdfc50082015-08-21 11:50:55 -0400299int16_t spvOpcodeResultIdIndex(spv_opcode_desc entry) {
David Neto78c3b432015-08-27 13:03:52 -0400300 for (int16_t i = 0; i < entry->numTypes; ++i) {
Lei Zhangdfc50082015-08-21 11:50:55 -0400301 if (SPV_OPERAND_TYPE_RESULT_ID == entry->operandTypes[i]) return i;
302 }
303 return SPV_OPERAND_INVALID_RESULT_ID_INDEX;
304}
305
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100306int32_t spvOpcodeRequiresCapabilities(spv_opcode_desc entry) {
David Neto9db3a532015-10-07 16:58:38 -0400307 return entry->capabilities != 0;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100308}
309
310void spvInstructionCopy(const uint32_t *words, const Op opcode,
311 const uint16_t wordCount, const spv_endianness_t endian,
312 spv_instruction_t *pInst) {
313 pInst->opcode = opcode;
David Netob5dc8fc2015-10-06 16:22:00 -0400314 pInst->words.resize(wordCount);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100315 for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
316 pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
317 if (!wordIndex) {
318 uint16_t thisWordCount;
319 Op thisOpcode;
320 spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
321 assert(opcode == thisOpcode && wordCount == thisWordCount &&
322 "Endianness failed!");
323 }
324 }
325}
326
327const char *spvOpcodeString(const Op opcode) {
328#define CASE(OPCODE) \
329 case OPCODE: \
330 return #OPCODE;
331 switch (opcode) {
332 CASE(OpNop)
333 CASE(OpSource)
334 CASE(OpSourceExtension)
335 CASE(OpExtension)
336 CASE(OpExtInstImport)
337 CASE(OpMemoryModel)
338 CASE(OpEntryPoint)
339 CASE(OpExecutionMode)
340 CASE(OpTypeVoid)
341 CASE(OpTypeBool)
342 CASE(OpTypeInt)
343 CASE(OpTypeFloat)
344 CASE(OpTypeVector)
345 CASE(OpTypeMatrix)
346 CASE(OpTypeSampler)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100347 CASE(OpTypeArray)
348 CASE(OpTypeRuntimeArray)
349 CASE(OpTypeStruct)
350 CASE(OpTypeOpaque)
351 CASE(OpTypePointer)
352 CASE(OpTypeFunction)
353 CASE(OpTypeEvent)
354 CASE(OpTypeDeviceEvent)
355 CASE(OpTypeReserveId)
356 CASE(OpTypeQueue)
357 CASE(OpTypePipe)
358 CASE(OpConstantTrue)
359 CASE(OpConstantFalse)
360 CASE(OpConstant)
361 CASE(OpConstantComposite)
362 CASE(OpConstantSampler)
363 CASE(OpConstantNull)
364 CASE(OpSpecConstantTrue)
365 CASE(OpSpecConstantFalse)
366 CASE(OpSpecConstant)
367 CASE(OpSpecConstantComposite)
368 CASE(OpVariable)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100369 CASE(OpFunction)
370 CASE(OpFunctionParameter)
371 CASE(OpFunctionEnd)
372 CASE(OpFunctionCall)
373 CASE(OpExtInst)
374 CASE(OpUndef)
375 CASE(OpLoad)
376 CASE(OpStore)
377 CASE(OpPhi)
378 CASE(OpDecorationGroup)
379 CASE(OpDecorate)
380 CASE(OpMemberDecorate)
381 CASE(OpGroupDecorate)
382 CASE(OpGroupMemberDecorate)
383 CASE(OpName)
384 CASE(OpMemberName)
385 CASE(OpString)
386 CASE(OpLine)
387 CASE(OpVectorExtractDynamic)
388 CASE(OpVectorInsertDynamic)
389 CASE(OpVectorShuffle)
390 CASE(OpCompositeConstruct)
391 CASE(OpCompositeExtract)
392 CASE(OpCompositeInsert)
393 CASE(OpCopyObject)
394 CASE(OpCopyMemory)
395 CASE(OpCopyMemorySized)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100396 CASE(OpAccessChain)
397 CASE(OpInBoundsAccessChain)
398 CASE(OpSNegate)
399 CASE(OpFNegate)
400 CASE(OpNot)
401 CASE(OpAny)
402 CASE(OpAll)
403 CASE(OpConvertFToU)
404 CASE(OpConvertFToS)
405 CASE(OpConvertSToF)
406 CASE(OpConvertUToF)
407 CASE(OpUConvert)
408 CASE(OpSConvert)
409 CASE(OpFConvert)
410 CASE(OpConvertPtrToU)
411 CASE(OpConvertUToPtr)
412 CASE(OpPtrCastToGeneric)
413 CASE(OpGenericCastToPtr)
414 CASE(OpBitcast)
415 CASE(OpTranspose)
416 CASE(OpIsNan)
417 CASE(OpIsInf)
418 CASE(OpIsFinite)
419 CASE(OpIsNormal)
420 CASE(OpSignBitSet)
421 CASE(OpLessOrGreater)
422 CASE(OpOrdered)
423 CASE(OpUnordered)
424 CASE(OpArrayLength)
425 CASE(OpIAdd)
426 CASE(OpFAdd)
427 CASE(OpISub)
428 CASE(OpFSub)
429 CASE(OpIMul)
430 CASE(OpFMul)
431 CASE(OpUDiv)
432 CASE(OpSDiv)
433 CASE(OpFDiv)
434 CASE(OpUMod)
435 CASE(OpSRem)
436 CASE(OpSMod)
437 CASE(OpFRem)
438 CASE(OpFMod)
439 CASE(OpVectorTimesScalar)
440 CASE(OpMatrixTimesScalar)
441 CASE(OpVectorTimesMatrix)
442 CASE(OpMatrixTimesVector)
443 CASE(OpMatrixTimesMatrix)
444 CASE(OpOuterProduct)
445 CASE(OpDot)
446 CASE(OpShiftRightLogical)
447 CASE(OpShiftRightArithmetic)
448 CASE(OpShiftLeftLogical)
449 CASE(OpLogicalOr)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100450 CASE(OpLogicalAnd)
451 CASE(OpBitwiseOr)
452 CASE(OpBitwiseXor)
453 CASE(OpBitwiseAnd)
454 CASE(OpSelect)
455 CASE(OpIEqual)
456 CASE(OpFOrdEqual)
457 CASE(OpFUnordEqual)
458 CASE(OpINotEqual)
459 CASE(OpFOrdNotEqual)
460 CASE(OpFUnordNotEqual)
461 CASE(OpULessThan)
462 CASE(OpSLessThan)
463 CASE(OpFOrdLessThan)
464 CASE(OpFUnordLessThan)
465 CASE(OpUGreaterThan)
466 CASE(OpSGreaterThan)
467 CASE(OpFOrdGreaterThan)
468 CASE(OpFUnordGreaterThan)
469 CASE(OpULessThanEqual)
470 CASE(OpSLessThanEqual)
471 CASE(OpFOrdLessThanEqual)
472 CASE(OpFUnordLessThanEqual)
473 CASE(OpUGreaterThanEqual)
474 CASE(OpSGreaterThanEqual)
475 CASE(OpFOrdGreaterThanEqual)
476 CASE(OpFUnordGreaterThanEqual)
477 CASE(OpDPdx)
478 CASE(OpDPdy)
479 CASE(OpFwidth)
480 CASE(OpDPdxFine)
481 CASE(OpDPdyFine)
482 CASE(OpFwidthFine)
483 CASE(OpDPdxCoarse)
484 CASE(OpDPdyCoarse)
485 CASE(OpFwidthCoarse)
486 CASE(OpEmitVertex)
487 CASE(OpEndPrimitive)
488 CASE(OpEmitStreamVertex)
489 CASE(OpEndStreamPrimitive)
490 CASE(OpControlBarrier)
491 CASE(OpMemoryBarrier)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100492 CASE(OpAtomicLoad)
493 CASE(OpAtomicStore)
494 CASE(OpAtomicExchange)
495 CASE(OpAtomicCompareExchange)
496 CASE(OpAtomicCompareExchangeWeak)
497 CASE(OpAtomicIIncrement)
498 CASE(OpAtomicIDecrement)
499 CASE(OpAtomicIAdd)
500 CASE(OpAtomicISub)
501 CASE(OpAtomicUMin)
502 CASE(OpAtomicUMax)
503 CASE(OpAtomicAnd)
504 CASE(OpAtomicOr)
505 CASE(OpAtomicXor)
506 CASE(OpLoopMerge)
507 CASE(OpSelectionMerge)
508 CASE(OpLabel)
509 CASE(OpBranch)
510 CASE(OpBranchConditional)
511 CASE(OpSwitch)
512 CASE(OpKill)
513 CASE(OpReturn)
514 CASE(OpReturnValue)
515 CASE(OpUnreachable)
516 CASE(OpLifetimeStart)
517 CASE(OpLifetimeStop)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100518 CASE(OpAsyncGroupCopy)
519 CASE(OpWaitGroupEvents)
520 CASE(OpGroupAll)
521 CASE(OpGroupAny)
522 CASE(OpGroupBroadcast)
523 CASE(OpGroupIAdd)
524 CASE(OpGroupFAdd)
525 CASE(OpGroupFMin)
526 CASE(OpGroupUMin)
527 CASE(OpGroupSMin)
528 CASE(OpGroupFMax)
529 CASE(OpGroupUMax)
530 CASE(OpGroupSMax)
531 CASE(OpGenericCastToPtrExplicit)
532 CASE(OpGenericPtrMemSemantics)
533 CASE(OpReadPipe)
534 CASE(OpWritePipe)
535 CASE(OpReservedReadPipe)
536 CASE(OpReservedWritePipe)
537 CASE(OpReserveReadPipePackets)
538 CASE(OpReserveWritePipePackets)
539 CASE(OpCommitReadPipe)
540 CASE(OpCommitWritePipe)
541 CASE(OpIsValidReserveId)
542 CASE(OpGetNumPipePackets)
543 CASE(OpGetMaxPipePackets)
544 CASE(OpGroupReserveReadPipePackets)
545 CASE(OpGroupReserveWritePipePackets)
546 CASE(OpGroupCommitReadPipe)
547 CASE(OpGroupCommitWritePipe)
548 CASE(OpEnqueueMarker)
549 CASE(OpEnqueueKernel)
550 CASE(OpGetKernelNDrangeSubGroupCount)
551 CASE(OpGetKernelNDrangeMaxSubGroupSize)
552 CASE(OpGetKernelWorkGroupSize)
553 CASE(OpGetKernelPreferredWorkGroupSizeMultiple)
554 CASE(OpRetainEvent)
555 CASE(OpReleaseEvent)
556 CASE(OpCreateUserEvent)
557 CASE(OpIsValidEvent)
558 CASE(OpSetUserEventStatus)
559 CASE(OpCaptureEventProfilingInfo)
560 CASE(OpGetDefaultQueue)
561 CASE(OpBuildNDRange)
562 default:
563 assert(0 && "Unreachable!");
564 }
565#undef CASE
566 return "unknown";
567}
568
569int32_t spvOpcodeIsType(const Op opcode) {
570 switch (opcode) {
571 case OpTypeVoid:
572 case OpTypeBool:
573 case OpTypeInt:
574 case OpTypeFloat:
575 case OpTypeVector:
576 case OpTypeMatrix:
577 case OpTypeSampler:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100578 case OpTypeArray:
579 case OpTypeRuntimeArray:
580 case OpTypeStruct:
581 case OpTypeOpaque:
582 case OpTypePointer:
583 case OpTypeFunction:
584 case OpTypeEvent:
585 case OpTypeDeviceEvent:
586 case OpTypeReserveId:
587 case OpTypeQueue:
588 case OpTypePipe:
589 return true;
590 default:
591 return false;
592 }
593}
594
595int32_t spvOpcodeIsScalarType(const Op opcode) {
596 switch (opcode) {
597 case OpTypeInt:
598 case OpTypeFloat:
599 return true;
600 default:
601 return false;
602 }
603}
604
605int32_t spvOpcodeIsConstant(const Op opcode) {
606 switch (opcode) {
607 case OpConstantTrue:
608 case OpConstantFalse:
609 case OpConstant:
610 case OpConstantComposite:
611 case OpConstantSampler:
612 // case OpConstantNull:
613 case OpConstantNull:
614 case OpSpecConstantTrue:
615 case OpSpecConstantFalse:
616 case OpSpecConstant:
617 case OpSpecConstantComposite:
618 // case OpSpecConstantOp:
619 return true;
620 default:
621 return false;
622 }
623}
624
625int32_t spvOpcodeIsComposite(const Op opcode) {
626 switch (opcode) {
627 case OpTypeVector:
628 case OpTypeMatrix:
629 case OpTypeArray:
630 case OpTypeStruct:
631 return true;
632 default:
633 return false;
634 }
635}
636
637int32_t spvOpcodeAreTypesEqual(const spv_instruction_t *pTypeInst0,
638 const spv_instruction_t *pTypeInst1) {
Lei Zhang40056702015-09-11 14:31:27 -0400639 if (pTypeInst0->opcode != pTypeInst1->opcode) return false;
640 if (pTypeInst0->words[1] != pTypeInst1->words[1]) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100641 return true;
642}
643
644int32_t spvOpcodeIsPointer(const Op opcode) {
645 switch (opcode) {
646 case OpVariable:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100647 case OpAccessChain:
648 case OpInBoundsAccessChain:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100649 case OpFunctionParameter:
650 return true;
651 default:
652 return false;
653 }
654}
655
656int32_t spvOpcodeIsObject(const Op opcode) {
657 switch (opcode) {
658 case OpConstantTrue:
659 case OpConstantFalse:
660 case OpConstant:
661 case OpConstantComposite:
662 // TODO: case OpConstantSampler:
663 case OpConstantNull:
664 case OpSpecConstantTrue:
665 case OpSpecConstantFalse:
666 case OpSpecConstant:
667 case OpSpecConstantComposite:
668 // TODO: case OpSpecConstantOp:
669 case OpVariable:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100670 case OpAccessChain:
671 case OpInBoundsAccessChain:
672 case OpConvertFToU:
673 case OpConvertFToS:
674 case OpConvertSToF:
675 case OpConvertUToF:
676 case OpUConvert:
677 case OpSConvert:
678 case OpFConvert:
679 case OpConvertPtrToU:
680 // TODO: case OpConvertUToPtr:
681 case OpPtrCastToGeneric:
682 // TODO: case OpGenericCastToPtr:
683 case OpBitcast:
684 // TODO: case OpGenericCastToPtrExplicit:
685 case OpSatConvertSToU:
686 case OpSatConvertUToS:
687 case OpVectorExtractDynamic:
688 case OpCompositeConstruct:
689 case OpCompositeExtract:
690 case OpCopyObject:
691 case OpTranspose:
692 case OpSNegate:
693 case OpFNegate:
694 case OpNot:
695 case OpIAdd:
696 case OpFAdd:
697 case OpISub:
698 case OpFSub:
699 case OpIMul:
700 case OpFMul:
701 case OpUDiv:
702 case OpSDiv:
703 case OpFDiv:
704 case OpUMod:
705 case OpSRem:
706 case OpSMod:
707 case OpVectorTimesScalar:
708 case OpMatrixTimesScalar:
709 case OpVectorTimesMatrix:
710 case OpMatrixTimesVector:
711 case OpMatrixTimesMatrix:
712 case OpOuterProduct:
713 case OpDot:
714 case OpShiftRightLogical:
715 case OpShiftRightArithmetic:
716 case OpShiftLeftLogical:
717 case OpBitwiseOr:
718 case OpBitwiseXor:
719 case OpBitwiseAnd:
720 case OpAny:
721 case OpAll:
722 case OpIsNan:
723 case OpIsInf:
724 case OpIsFinite:
725 case OpIsNormal:
726 case OpSignBitSet:
727 case OpLessOrGreater:
728 case OpOrdered:
729 case OpUnordered:
730 case OpLogicalOr:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100731 case OpLogicalAnd:
732 case OpSelect:
733 case OpIEqual:
734 case OpFOrdEqual:
735 case OpFUnordEqual:
736 case OpINotEqual:
737 case OpFOrdNotEqual:
738 case OpFUnordNotEqual:
739 case OpULessThan:
740 case OpSLessThan:
741 case OpFOrdLessThan:
742 case OpFUnordLessThan:
743 case OpUGreaterThan:
744 case OpSGreaterThan:
745 case OpFOrdGreaterThan:
746 case OpFUnordGreaterThan:
747 case OpULessThanEqual:
748 case OpSLessThanEqual:
749 case OpFOrdLessThanEqual:
750 case OpFUnordLessThanEqual:
751 case OpUGreaterThanEqual:
752 case OpSGreaterThanEqual:
753 case OpFOrdGreaterThanEqual:
754 case OpFUnordGreaterThanEqual:
755 case OpDPdx:
756 case OpDPdy:
757 case OpFwidth:
758 case OpDPdxFine:
759 case OpDPdyFine:
760 case OpFwidthFine:
761 case OpDPdxCoarse:
762 case OpDPdyCoarse:
763 case OpFwidthCoarse:
764 case OpReturnValue:
765 return true;
766 default:
767 return false;
768 }
769}
770
771int32_t spvOpcodeIsBasicTypeNullable(Op opcode) {
772 switch (opcode) {
773 case OpTypeBool:
774 case OpTypeInt:
775 case OpTypeFloat:
776 case OpTypePointer:
777 case OpTypeEvent:
778 case OpTypeDeviceEvent:
779 case OpTypeReserveId:
780 case OpTypeQueue:
781 return true;
782 default:
783 return false;
784 }
785}
786
787int32_t spvInstructionIsInBasicBlock(const spv_instruction_t *pFirstInst,
788 const spv_instruction_t *pInst) {
789 while (pFirstInst != pInst) {
Lei Zhang40056702015-09-11 14:31:27 -0400790 if (OpFunction == pInst->opcode) break;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100791 pInst--;
792 }
Lei Zhang40056702015-09-11 14:31:27 -0400793 if (OpFunction != pInst->opcode) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100794 return true;
795}
796
797int32_t spvOpcodeIsValue(Op opcode) {
Lei Zhang40056702015-09-11 14:31:27 -0400798 if (spvOpcodeIsPointer(opcode)) return true;
799 if (spvOpcodeIsConstant(opcode)) return true;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100800 switch (opcode) {
801 case OpLoad:
802 // TODO: Other Opcode's resulting in a value
803 return true;
804 default:
805 return false;
806 }
807}
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400808
809int32_t spvOpcodeGeneratesType(Op op) {
810 switch(op) {
811 case OpTypeVoid:
812 case OpTypeBool:
813 case OpTypeInt:
814 case OpTypeFloat:
815 case OpTypeVector:
816 case OpTypeMatrix:
817 case OpTypeImage:
818 case OpTypeSampler:
819 case OpTypeSampledImage:
820 case OpTypeArray:
821 case OpTypeRuntimeArray:
822 case OpTypeStruct:
823 case OpTypeOpaque:
824 case OpTypePointer:
825 case OpTypeFunction:
826 case OpTypeEvent:
827 case OpTypeDeviceEvent:
828 case OpTypeReserveId:
829 case OpTypeQueue:
830 case OpTypePipe:
831 case OpTypeForwardPointer:
832 return true;
833 default:;
834 }
835 return 0;
836}