blob: dc5872f8edfae670eae3fc63938c210cc879d767 [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"
29#include "opcode.h"
30
31#include <assert.h>
32#include <string.h>
33
David Neto78c3b432015-08-27 13:03:52 -040034namespace {
35
36// Descriptions of each opcode. Each entry describes the format of the
37// instruction that follows a particular opcode.
38//
39// Most fields are initialized statically by including an automatically
40// generated file.
41// The operandTypes fields are initialized during spvOpcodeInitialize().
42//
43// TODO(dneto): Some of the macros are quite unreadable. We could make
44// good use of constexpr functions, but some compilers don't support that yet.
45spv_opcode_desc_t opcodeTableEntries[] = {
46#define EmptyList {}
47#define List(...) {__VA_ARGS__}
48#define Capability(X) Capability##X
49#define CapabilityNone -1
David Netoe0890da2015-09-24 15:45:59 -040050// TODO(dneto): Some things can be enabled by one of two different capabilities.
51// The capabilities field in spv_operand_desc_t can't handle that yet.
52// Maybe have to make it a 64-bit mask. Currently there are 54 distinct
53// capabilities.
54// For now, just select the first one. This must be fixed for the validator
55// to work.
56#define Capability2(X,Y) Capability##X
David Neto78c3b432015-08-27 13:03:52 -040057#define Instruction(Name,HasResult,HasType,NumLogicalOperands,NumCapabilities,CapabilityRequired,IsVariable,LogicalArgsList) \
58 { #Name, \
59 Op##Name, \
David Netoc9b51522015-09-08 14:59:57 -040060 ((CapabilityRequired != CapabilityNone ? SPV_OPCODE_FLAGS_CAPABILITIES : 0)), \
David Neto78c3b432015-08-27 13:03:52 -040061 uint32_t(CapabilityRequired), \
62 0, {}, /* Filled in later. Operand list, including result id and type id, if needed */ \
63 HasResult, \
64 HasType, \
65 LogicalArgsList },
66#include "opcode.inc"
67#undef EmptyList
68#undef List
69#undef Capability
70#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
81// logic) to the operand type required by the parser.
82// This only applies to logical operands.
Lei Zhang40056702015-09-11 14:31:27 -040083spv_operand_type_t convertOperandClassToType(spv::Op opcode,
84 spv::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) {
David Neto78c3b432015-08-27 13:03:52 -040090 case spv::OpLoad:
91 case spv::OpStore:
92 case spv::OpCopyMemory:
93 case spv::OpCopyMemorySized:
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;
David Neto78c3b432015-08-27 13:03:52 -040097 case spv::OpExecutionMode:
98 return SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE;
99 default:
100 break;
101 }
Lei Zhangb41d1502015-09-14 15:22:23 -0400102 } else if (operandClass == OperandVariableLiterals) {
103 if (opcode == spv::OpConstant || opcode == spv::OpSpecConstant)
104 return SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER;
David Neto78c3b432015-08-27 13:03:52 -0400105 }
106
107 switch(operandClass) {
108 case OperandNone: return SPV_OPERAND_TYPE_NONE;
109 case OperandId: return SPV_OPERAND_TYPE_ID;
110 case OperandOptionalId: return SPV_OPERAND_TYPE_OPTIONAL_ID;
111 case OperandOptionalImage: return SPV_OPERAND_TYPE_OPTIONAL_IMAGE; // TODO(dneto): This is variable.
112 case OperandVariableIds: return SPV_OPERAND_TYPE_VARIABLE_ID;
113 case OperandOptionalLiteral: return SPV_OPERAND_TYPE_OPTIONAL_LITERAL;
114 case OperandOptionalLiteralString: return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING;
115 case OperandVariableLiterals: return SPV_OPERAND_TYPE_VARIABLE_LITERAL;
116 case OperandLiteralNumber: return SPV_OPERAND_TYPE_LITERAL_NUMBER;
117 case OperandLiteralString: return SPV_OPERAND_TYPE_LITERAL_STRING;
118 case OperandSource: return SPV_OPERAND_TYPE_SOURCE_LANGUAGE;
119 case OperandExecutionModel: return SPV_OPERAND_TYPE_EXECUTION_MODEL;
120 case OperandAddressing: return SPV_OPERAND_TYPE_ADDRESSING_MODEL;
121 case OperandMemory: return SPV_OPERAND_TYPE_MEMORY_MODEL;
122 case OperandExecutionMode: return SPV_OPERAND_TYPE_EXECUTION_MODE;
123 case OperandStorage: return SPV_OPERAND_TYPE_STORAGE_CLASS;
124 case OperandDimensionality: return SPV_OPERAND_TYPE_DIMENSIONALITY;
125 case OperandSamplerAddressingMode: return SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE;
126 case OperandSamplerFilterMode: return SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE;
David Netob30a0c52015-09-16 15:56:43 -0400127 case OperandSamplerImageFormat: return SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT;
David Neto78c3b432015-08-27 13:03:52 -0400128 case OperandImageChannelOrder: return SPV_OPERAND_TYPE_NONE; //TODO
129 case OperandImageChannelDataType: return SPV_OPERAND_TYPE_NONE; //TODO
130 case OperandImageOperands: return SPV_OPERAND_TYPE_NONE; //TODO
131 case OperandFPFastMath: return SPV_OPERAND_TYPE_FP_FAST_MATH_MODE;
132 case OperandFPRoundingMode: return SPV_OPERAND_TYPE_FP_ROUNDING_MODE;
133 case OperandLinkageType: return SPV_OPERAND_TYPE_LINKAGE_TYPE;
134 case OperandAccessQualifier: return SPV_OPERAND_TYPE_ACCESS_QUALIFIER;
135 case OperandFuncParamAttr: return SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE;
136 case OperandDecoration: return SPV_OPERAND_TYPE_DECORATION;
137 case OperandBuiltIn: return SPV_OPERAND_TYPE_BUILT_IN;
138 case OperandSelect: return SPV_OPERAND_TYPE_SELECTION_CONTROL;
139 case OperandLoop: return SPV_OPERAND_TYPE_LOOP_CONTROL;
140 case OperandFunction: return SPV_OPERAND_TYPE_FUNCTION_CONTROL;
141 case OperandMemorySemantics: return SPV_OPERAND_TYPE_MEMORY_SEMANTICS;
142 case OperandMemoryAccess:
143 // This case does not occur in Rev 31.
David Neto3fca4cd2015-09-17 17:39:45 -0400144 // We expect that it will become SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
David Neto78c3b432015-08-27 13:03:52 -0400145 // and we can remove the special casing above for memory operation
146 // instructions.
147 break;
148 case OperandScope: return SPV_OPERAND_TYPE_EXECUTION_SCOPE;
149 case OperandGroupOperation: return SPV_OPERAND_TYPE_GROUP_OPERATION;
150 case OperandKernelEnqueueFlags: return SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS;
151 case OperandKernelProfilingInfo: return SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO;
152 case OperandCapability: return SPV_OPERAND_TYPE_CAPABILITY;
153
154 // Used by GroupMemberDecorate
155 case OperandVariableIdLiteral: return SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL;
156
157 // Used by Switch
158 case OperandVariableLiteralId: return SPV_OPERAND_TYPE_VARIABLE_LITERAL_ID;
159
160 // These exceptional cases shouldn't occur.
161 case OperandCount:
162 default:
163 break;
164 }
165 assert(0 && "Unexpected operand class");
166 return SPV_OPERAND_TYPE_NONE;
167}
168
Lei Zhanga94701d2015-09-14 10:05:37 -0400169} // anonymous namespace
David Neto78c3b432015-08-27 13:03:52 -0400170
171// Finish populating the opcodeTableEntries array.
172void spvOpcodeTableInitialize() {
173 // Compute the operandTypes field for each entry.
Lei Zhanga94701d2015-09-14 10:05:37 -0400174 for (auto &opcode : opcodeTableEntries) {
David Neto78c3b432015-08-27 13:03:52 -0400175 opcode.numTypes = 0;
176 // Type ID always comes first, if present.
177 if (opcode.hasType)
178 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_ID;
179 // Result ID always comes next, if present
180 if (opcode.hasResult)
181 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_RESULT_ID;
Lei Zhanga94701d2015-09-14 10:05:37 -0400182 const uint16_t maxNumOperands =
183 sizeof(opcode.operandTypes) / sizeof(opcode.operandTypes[0]);
184 const uint16_t maxNumClasses =
185 sizeof(opcode.operandClass) / sizeof(opcode.operandClass[0]);
186 for (uint16_t classIndex = 0;
187 opcode.numTypes < maxNumOperands && classIndex < maxNumClasses;
188 classIndex++) {
David Neto78c3b432015-08-27 13:03:52 -0400189 const OperandClass operandClass = opcode.operandClass[classIndex];
Lei Zhanga94701d2015-09-14 10:05:37 -0400190 opcode.operandTypes[opcode.numTypes++] =
191 convertOperandClassToType(opcode.opcode, operandClass);
David Neto78c3b432015-08-27 13:03:52 -0400192 // The OperandNone value is not explicitly represented in the .inc file.
193 // However, it is the zero value, and is created via implicit value
194 // initialization.
195 if (operandClass == OperandNone) {
196 opcode.numTypes--;
197 break;
198 }
199 }
200 // We should have written the terminating SPV_OPERAND_TYPE_NONE entry, but
201 // also without overflowing.
Lei Zhanga94701d2015-09-14 10:05:37 -0400202 assert((opcode.numTypes < maxNumOperands) &&
203 "Operand class list is too long. Expand "
204 "spv_opcode_desc_t.operandClass");
David Neto78c3b432015-08-27 13:03:52 -0400205 }
206 opcodeTableInitialized = true;
207}
208
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100209const char *spvGeneratorStr(uint32_t generator) {
210 switch (generator) {
211 case SPV_GENERATOR_KHRONOS:
212 return "Khronos";
213 case SPV_GENERATOR_VALVE:
214 return "Valve";
215 case SPV_GENERATOR_LUNARG:
216 return "LunarG";
217 case SPV_GENERATOR_CODEPLAY:
218 return "Codeplay Software Ltd.";
219 default:
220 return "Unknown";
221 }
222}
223
224uint32_t spvOpcodeMake(uint16_t wordCount, Op opcode) {
225 return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
226}
227
228void spvOpcodeSplit(const uint32_t word, uint16_t *pWordCount, Op *pOpcode) {
229 if (pWordCount) {
230 *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
231 }
232 if (pOpcode) {
233 *pOpcode = (Op)(0x0000ffff & word);
234 }
235}
236
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100237spv_result_t spvOpcodeTableGet(spv_opcode_table *pInstTable) {
Lei Zhang40056702015-09-11 14:31:27 -0400238 if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100239
David Neto78c3b432015-08-27 13:03:52 -0400240 static spv_opcode_table_t table = {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100241 sizeof(opcodeTableEntries) / sizeof(spv_opcode_desc_t),
242 opcodeTableEntries};
243
David Neto78c3b432015-08-27 13:03:52 -0400244 // TODO(dneto): Consider thread safety of initialization.
245 // That is, ordering effects of the flag vs. the table updates.
Lei Zhang40056702015-09-11 14:31:27 -0400246 if (!opcodeTableInitialized) spvOpcodeTableInitialize();
David Neto78c3b432015-08-27 13:03:52 -0400247
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100248 *pInstTable = &table;
249
250 return SPV_SUCCESS;
251}
252
253spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
254 const char *name,
255 spv_opcode_desc *pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400256 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
257 if (!table) return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100258
259 // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
260 // preferable but the table requires sorting on the Opcode name, but it's
261 // static
262 // const initialized and matches the order of the spec.
263 const size_t nameLength = strlen(name);
264 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
265 if (nameLength == strlen(table->entries[opcodeIndex].name) &&
266 !strncmp(name, table->entries[opcodeIndex].name, nameLength)) {
267 // NOTE: Found out Opcode!
268 *pEntry = &table->entries[opcodeIndex];
269 return SPV_SUCCESS;
270 }
271 }
272
273 return SPV_ERROR_INVALID_LOOKUP;
274}
275
276spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
277 const Op opcode,
278 spv_opcode_desc *pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400279 if (!table) return SPV_ERROR_INVALID_TABLE;
280 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100281
282 // TODO: As above this lookup is not optimal.
283 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
284 if (opcode == table->entries[opcodeIndex].opcode) {
285 // NOTE: Found the Opcode!
286 *pEntry = &table->entries[opcodeIndex];
287 return SPV_SUCCESS;
288 }
289 }
290
291 return SPV_ERROR_INVALID_LOOKUP;
292}
293
Lei Zhangdfc50082015-08-21 11:50:55 -0400294int16_t spvOpcodeResultIdIndex(spv_opcode_desc entry) {
David Neto78c3b432015-08-27 13:03:52 -0400295 for (int16_t i = 0; i < entry->numTypes; ++i) {
Lei Zhangdfc50082015-08-21 11:50:55 -0400296 if (SPV_OPERAND_TYPE_RESULT_ID == entry->operandTypes[i]) return i;
297 }
298 return SPV_OPERAND_INVALID_RESULT_ID_INDEX;
299}
300
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100301int32_t spvOpcodeRequiresCapabilities(spv_opcode_desc entry) {
302 return SPV_OPCODE_FLAGS_CAPABILITIES ==
303 (SPV_OPCODE_FLAGS_CAPABILITIES & entry->flags);
304}
305
306void spvInstructionCopy(const uint32_t *words, const Op opcode,
307 const uint16_t wordCount, const spv_endianness_t endian,
308 spv_instruction_t *pInst) {
309 pInst->opcode = opcode;
310 pInst->wordCount = wordCount;
311 for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
312 pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
313 if (!wordIndex) {
314 uint16_t thisWordCount;
315 Op thisOpcode;
316 spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
317 assert(opcode == thisOpcode && wordCount == thisWordCount &&
318 "Endianness failed!");
319 }
320 }
321}
322
323const char *spvOpcodeString(const Op opcode) {
324#define CASE(OPCODE) \
325 case OPCODE: \
326 return #OPCODE;
327 switch (opcode) {
328 CASE(OpNop)
329 CASE(OpSource)
330 CASE(OpSourceExtension)
331 CASE(OpExtension)
332 CASE(OpExtInstImport)
333 CASE(OpMemoryModel)
334 CASE(OpEntryPoint)
335 CASE(OpExecutionMode)
336 CASE(OpTypeVoid)
337 CASE(OpTypeBool)
338 CASE(OpTypeInt)
339 CASE(OpTypeFloat)
340 CASE(OpTypeVector)
341 CASE(OpTypeMatrix)
342 CASE(OpTypeSampler)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100343 CASE(OpTypeArray)
344 CASE(OpTypeRuntimeArray)
345 CASE(OpTypeStruct)
346 CASE(OpTypeOpaque)
347 CASE(OpTypePointer)
348 CASE(OpTypeFunction)
349 CASE(OpTypeEvent)
350 CASE(OpTypeDeviceEvent)
351 CASE(OpTypeReserveId)
352 CASE(OpTypeQueue)
353 CASE(OpTypePipe)
354 CASE(OpConstantTrue)
355 CASE(OpConstantFalse)
356 CASE(OpConstant)
357 CASE(OpConstantComposite)
358 CASE(OpConstantSampler)
359 CASE(OpConstantNull)
360 CASE(OpSpecConstantTrue)
361 CASE(OpSpecConstantFalse)
362 CASE(OpSpecConstant)
363 CASE(OpSpecConstantComposite)
364 CASE(OpVariable)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100365 CASE(OpFunction)
366 CASE(OpFunctionParameter)
367 CASE(OpFunctionEnd)
368 CASE(OpFunctionCall)
369 CASE(OpExtInst)
370 CASE(OpUndef)
371 CASE(OpLoad)
372 CASE(OpStore)
373 CASE(OpPhi)
374 CASE(OpDecorationGroup)
375 CASE(OpDecorate)
376 CASE(OpMemberDecorate)
377 CASE(OpGroupDecorate)
378 CASE(OpGroupMemberDecorate)
379 CASE(OpName)
380 CASE(OpMemberName)
381 CASE(OpString)
382 CASE(OpLine)
383 CASE(OpVectorExtractDynamic)
384 CASE(OpVectorInsertDynamic)
385 CASE(OpVectorShuffle)
386 CASE(OpCompositeConstruct)
387 CASE(OpCompositeExtract)
388 CASE(OpCompositeInsert)
389 CASE(OpCopyObject)
390 CASE(OpCopyMemory)
391 CASE(OpCopyMemorySized)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100392 CASE(OpAccessChain)
393 CASE(OpInBoundsAccessChain)
394 CASE(OpSNegate)
395 CASE(OpFNegate)
396 CASE(OpNot)
397 CASE(OpAny)
398 CASE(OpAll)
399 CASE(OpConvertFToU)
400 CASE(OpConvertFToS)
401 CASE(OpConvertSToF)
402 CASE(OpConvertUToF)
403 CASE(OpUConvert)
404 CASE(OpSConvert)
405 CASE(OpFConvert)
406 CASE(OpConvertPtrToU)
407 CASE(OpConvertUToPtr)
408 CASE(OpPtrCastToGeneric)
409 CASE(OpGenericCastToPtr)
410 CASE(OpBitcast)
411 CASE(OpTranspose)
412 CASE(OpIsNan)
413 CASE(OpIsInf)
414 CASE(OpIsFinite)
415 CASE(OpIsNormal)
416 CASE(OpSignBitSet)
417 CASE(OpLessOrGreater)
418 CASE(OpOrdered)
419 CASE(OpUnordered)
420 CASE(OpArrayLength)
421 CASE(OpIAdd)
422 CASE(OpFAdd)
423 CASE(OpISub)
424 CASE(OpFSub)
425 CASE(OpIMul)
426 CASE(OpFMul)
427 CASE(OpUDiv)
428 CASE(OpSDiv)
429 CASE(OpFDiv)
430 CASE(OpUMod)
431 CASE(OpSRem)
432 CASE(OpSMod)
433 CASE(OpFRem)
434 CASE(OpFMod)
435 CASE(OpVectorTimesScalar)
436 CASE(OpMatrixTimesScalar)
437 CASE(OpVectorTimesMatrix)
438 CASE(OpMatrixTimesVector)
439 CASE(OpMatrixTimesMatrix)
440 CASE(OpOuterProduct)
441 CASE(OpDot)
442 CASE(OpShiftRightLogical)
443 CASE(OpShiftRightArithmetic)
444 CASE(OpShiftLeftLogical)
445 CASE(OpLogicalOr)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100446 CASE(OpLogicalAnd)
447 CASE(OpBitwiseOr)
448 CASE(OpBitwiseXor)
449 CASE(OpBitwiseAnd)
450 CASE(OpSelect)
451 CASE(OpIEqual)
452 CASE(OpFOrdEqual)
453 CASE(OpFUnordEqual)
454 CASE(OpINotEqual)
455 CASE(OpFOrdNotEqual)
456 CASE(OpFUnordNotEqual)
457 CASE(OpULessThan)
458 CASE(OpSLessThan)
459 CASE(OpFOrdLessThan)
460 CASE(OpFUnordLessThan)
461 CASE(OpUGreaterThan)
462 CASE(OpSGreaterThan)
463 CASE(OpFOrdGreaterThan)
464 CASE(OpFUnordGreaterThan)
465 CASE(OpULessThanEqual)
466 CASE(OpSLessThanEqual)
467 CASE(OpFOrdLessThanEqual)
468 CASE(OpFUnordLessThanEqual)
469 CASE(OpUGreaterThanEqual)
470 CASE(OpSGreaterThanEqual)
471 CASE(OpFOrdGreaterThanEqual)
472 CASE(OpFUnordGreaterThanEqual)
473 CASE(OpDPdx)
474 CASE(OpDPdy)
475 CASE(OpFwidth)
476 CASE(OpDPdxFine)
477 CASE(OpDPdyFine)
478 CASE(OpFwidthFine)
479 CASE(OpDPdxCoarse)
480 CASE(OpDPdyCoarse)
481 CASE(OpFwidthCoarse)
482 CASE(OpEmitVertex)
483 CASE(OpEndPrimitive)
484 CASE(OpEmitStreamVertex)
485 CASE(OpEndStreamPrimitive)
486 CASE(OpControlBarrier)
487 CASE(OpMemoryBarrier)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100488 CASE(OpAtomicLoad)
489 CASE(OpAtomicStore)
490 CASE(OpAtomicExchange)
491 CASE(OpAtomicCompareExchange)
492 CASE(OpAtomicCompareExchangeWeak)
493 CASE(OpAtomicIIncrement)
494 CASE(OpAtomicIDecrement)
495 CASE(OpAtomicIAdd)
496 CASE(OpAtomicISub)
497 CASE(OpAtomicUMin)
498 CASE(OpAtomicUMax)
499 CASE(OpAtomicAnd)
500 CASE(OpAtomicOr)
501 CASE(OpAtomicXor)
502 CASE(OpLoopMerge)
503 CASE(OpSelectionMerge)
504 CASE(OpLabel)
505 CASE(OpBranch)
506 CASE(OpBranchConditional)
507 CASE(OpSwitch)
508 CASE(OpKill)
509 CASE(OpReturn)
510 CASE(OpReturnValue)
511 CASE(OpUnreachable)
512 CASE(OpLifetimeStart)
513 CASE(OpLifetimeStop)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100514 CASE(OpAsyncGroupCopy)
515 CASE(OpWaitGroupEvents)
516 CASE(OpGroupAll)
517 CASE(OpGroupAny)
518 CASE(OpGroupBroadcast)
519 CASE(OpGroupIAdd)
520 CASE(OpGroupFAdd)
521 CASE(OpGroupFMin)
522 CASE(OpGroupUMin)
523 CASE(OpGroupSMin)
524 CASE(OpGroupFMax)
525 CASE(OpGroupUMax)
526 CASE(OpGroupSMax)
527 CASE(OpGenericCastToPtrExplicit)
528 CASE(OpGenericPtrMemSemantics)
529 CASE(OpReadPipe)
530 CASE(OpWritePipe)
531 CASE(OpReservedReadPipe)
532 CASE(OpReservedWritePipe)
533 CASE(OpReserveReadPipePackets)
534 CASE(OpReserveWritePipePackets)
535 CASE(OpCommitReadPipe)
536 CASE(OpCommitWritePipe)
537 CASE(OpIsValidReserveId)
538 CASE(OpGetNumPipePackets)
539 CASE(OpGetMaxPipePackets)
540 CASE(OpGroupReserveReadPipePackets)
541 CASE(OpGroupReserveWritePipePackets)
542 CASE(OpGroupCommitReadPipe)
543 CASE(OpGroupCommitWritePipe)
544 CASE(OpEnqueueMarker)
545 CASE(OpEnqueueKernel)
546 CASE(OpGetKernelNDrangeSubGroupCount)
547 CASE(OpGetKernelNDrangeMaxSubGroupSize)
548 CASE(OpGetKernelWorkGroupSize)
549 CASE(OpGetKernelPreferredWorkGroupSizeMultiple)
550 CASE(OpRetainEvent)
551 CASE(OpReleaseEvent)
552 CASE(OpCreateUserEvent)
553 CASE(OpIsValidEvent)
554 CASE(OpSetUserEventStatus)
555 CASE(OpCaptureEventProfilingInfo)
556 CASE(OpGetDefaultQueue)
557 CASE(OpBuildNDRange)
558 default:
559 assert(0 && "Unreachable!");
560 }
561#undef CASE
562 return "unknown";
563}
564
565int32_t spvOpcodeIsType(const Op opcode) {
566 switch (opcode) {
567 case OpTypeVoid:
568 case OpTypeBool:
569 case OpTypeInt:
570 case OpTypeFloat:
571 case OpTypeVector:
572 case OpTypeMatrix:
573 case OpTypeSampler:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100574 case OpTypeArray:
575 case OpTypeRuntimeArray:
576 case OpTypeStruct:
577 case OpTypeOpaque:
578 case OpTypePointer:
579 case OpTypeFunction:
580 case OpTypeEvent:
581 case OpTypeDeviceEvent:
582 case OpTypeReserveId:
583 case OpTypeQueue:
584 case OpTypePipe:
585 return true;
586 default:
587 return false;
588 }
589}
590
591int32_t spvOpcodeIsScalarType(const Op opcode) {
592 switch (opcode) {
593 case OpTypeInt:
594 case OpTypeFloat:
595 return true;
596 default:
597 return false;
598 }
599}
600
601int32_t spvOpcodeIsConstant(const Op opcode) {
602 switch (opcode) {
603 case OpConstantTrue:
604 case OpConstantFalse:
605 case OpConstant:
606 case OpConstantComposite:
607 case OpConstantSampler:
608 // case OpConstantNull:
609 case OpConstantNull:
610 case OpSpecConstantTrue:
611 case OpSpecConstantFalse:
612 case OpSpecConstant:
613 case OpSpecConstantComposite:
614 // case OpSpecConstantOp:
615 return true;
616 default:
617 return false;
618 }
619}
620
621int32_t spvOpcodeIsComposite(const Op opcode) {
622 switch (opcode) {
623 case OpTypeVector:
624 case OpTypeMatrix:
625 case OpTypeArray:
626 case OpTypeStruct:
627 return true;
628 default:
629 return false;
630 }
631}
632
633int32_t spvOpcodeAreTypesEqual(const spv_instruction_t *pTypeInst0,
634 const spv_instruction_t *pTypeInst1) {
Lei Zhang40056702015-09-11 14:31:27 -0400635 if (pTypeInst0->opcode != pTypeInst1->opcode) return false;
636 if (pTypeInst0->words[1] != pTypeInst1->words[1]) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100637 return true;
638}
639
640int32_t spvOpcodeIsPointer(const Op opcode) {
641 switch (opcode) {
642 case OpVariable:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100643 case OpAccessChain:
644 case OpInBoundsAccessChain:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100645 case OpFunctionParameter:
646 return true;
647 default:
648 return false;
649 }
650}
651
652int32_t spvOpcodeIsObject(const Op opcode) {
653 switch (opcode) {
654 case OpConstantTrue:
655 case OpConstantFalse:
656 case OpConstant:
657 case OpConstantComposite:
658 // TODO: case OpConstantSampler:
659 case OpConstantNull:
660 case OpSpecConstantTrue:
661 case OpSpecConstantFalse:
662 case OpSpecConstant:
663 case OpSpecConstantComposite:
664 // TODO: case OpSpecConstantOp:
665 case OpVariable:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100666 case OpAccessChain:
667 case OpInBoundsAccessChain:
668 case OpConvertFToU:
669 case OpConvertFToS:
670 case OpConvertSToF:
671 case OpConvertUToF:
672 case OpUConvert:
673 case OpSConvert:
674 case OpFConvert:
675 case OpConvertPtrToU:
676 // TODO: case OpConvertUToPtr:
677 case OpPtrCastToGeneric:
678 // TODO: case OpGenericCastToPtr:
679 case OpBitcast:
680 // TODO: case OpGenericCastToPtrExplicit:
681 case OpSatConvertSToU:
682 case OpSatConvertUToS:
683 case OpVectorExtractDynamic:
684 case OpCompositeConstruct:
685 case OpCompositeExtract:
686 case OpCopyObject:
687 case OpTranspose:
688 case OpSNegate:
689 case OpFNegate:
690 case OpNot:
691 case OpIAdd:
692 case OpFAdd:
693 case OpISub:
694 case OpFSub:
695 case OpIMul:
696 case OpFMul:
697 case OpUDiv:
698 case OpSDiv:
699 case OpFDiv:
700 case OpUMod:
701 case OpSRem:
702 case OpSMod:
703 case OpVectorTimesScalar:
704 case OpMatrixTimesScalar:
705 case OpVectorTimesMatrix:
706 case OpMatrixTimesVector:
707 case OpMatrixTimesMatrix:
708 case OpOuterProduct:
709 case OpDot:
710 case OpShiftRightLogical:
711 case OpShiftRightArithmetic:
712 case OpShiftLeftLogical:
713 case OpBitwiseOr:
714 case OpBitwiseXor:
715 case OpBitwiseAnd:
716 case OpAny:
717 case OpAll:
718 case OpIsNan:
719 case OpIsInf:
720 case OpIsFinite:
721 case OpIsNormal:
722 case OpSignBitSet:
723 case OpLessOrGreater:
724 case OpOrdered:
725 case OpUnordered:
726 case OpLogicalOr:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100727 case OpLogicalAnd:
728 case OpSelect:
729 case OpIEqual:
730 case OpFOrdEqual:
731 case OpFUnordEqual:
732 case OpINotEqual:
733 case OpFOrdNotEqual:
734 case OpFUnordNotEqual:
735 case OpULessThan:
736 case OpSLessThan:
737 case OpFOrdLessThan:
738 case OpFUnordLessThan:
739 case OpUGreaterThan:
740 case OpSGreaterThan:
741 case OpFOrdGreaterThan:
742 case OpFUnordGreaterThan:
743 case OpULessThanEqual:
744 case OpSLessThanEqual:
745 case OpFOrdLessThanEqual:
746 case OpFUnordLessThanEqual:
747 case OpUGreaterThanEqual:
748 case OpSGreaterThanEqual:
749 case OpFOrdGreaterThanEqual:
750 case OpFUnordGreaterThanEqual:
751 case OpDPdx:
752 case OpDPdy:
753 case OpFwidth:
754 case OpDPdxFine:
755 case OpDPdyFine:
756 case OpFwidthFine:
757 case OpDPdxCoarse:
758 case OpDPdyCoarse:
759 case OpFwidthCoarse:
760 case OpReturnValue:
761 return true;
762 default:
763 return false;
764 }
765}
766
767int32_t spvOpcodeIsBasicTypeNullable(Op opcode) {
768 switch (opcode) {
769 case OpTypeBool:
770 case OpTypeInt:
771 case OpTypeFloat:
772 case OpTypePointer:
773 case OpTypeEvent:
774 case OpTypeDeviceEvent:
775 case OpTypeReserveId:
776 case OpTypeQueue:
777 return true;
778 default:
779 return false;
780 }
781}
782
783int32_t spvInstructionIsInBasicBlock(const spv_instruction_t *pFirstInst,
784 const spv_instruction_t *pInst) {
785 while (pFirstInst != pInst) {
Lei Zhang40056702015-09-11 14:31:27 -0400786 if (OpFunction == pInst->opcode) break;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100787 pInst--;
788 }
Lei Zhang40056702015-09-11 14:31:27 -0400789 if (OpFunction != pInst->opcode) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100790 return true;
791}
792
793int32_t spvOpcodeIsValue(Op opcode) {
Lei Zhang40056702015-09-11 14:31:27 -0400794 if (spvOpcodeIsPointer(opcode)) return true;
795 if (spvOpcodeIsConstant(opcode)) return true;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100796 switch (opcode) {
797 case OpLoad:
798 // TODO: Other Opcode's resulting in a value
799 return true;
800 default:
801 return false;
802 }
803}