blob: 0c897973c646f87610f4205a368713158112d96d [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
50#define Instruction(Name,HasResult,HasType,NumLogicalOperands,NumCapabilities,CapabilityRequired,IsVariable,LogicalArgsList) \
51 { #Name, \
52 Op##Name, \
David Netoc9b51522015-09-08 14:59:57 -040053 ((CapabilityRequired != CapabilityNone ? SPV_OPCODE_FLAGS_CAPABILITIES : 0)), \
David Neto78c3b432015-08-27 13:03:52 -040054 uint32_t(CapabilityRequired), \
55 0, {}, /* Filled in later. Operand list, including result id and type id, if needed */ \
56 HasResult, \
57 HasType, \
58 LogicalArgsList },
59#include "opcode.inc"
60#undef EmptyList
61#undef List
62#undef Capability
63#undef CapabilityNone
64#undef Instruction
65};
66
67// Has the opcodeTableEntries table been fully elaborated?
68// That is, are the operandTypes fields initialized?
69bool opcodeTableInitialized = false;
70
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010071// Opcode API
72
David Neto78c3b432015-08-27 13:03:52 -040073// Converts the given operand class enum (from the SPIR-V document generation
74// logic) to the operand type required by the parser.
75// This only applies to logical operands.
Lei Zhang40056702015-09-11 14:31:27 -040076spv_operand_type_t convertOperandClassToType(spv::Op opcode,
77 spv::OperandClass operandClass) {
David Neto78c3b432015-08-27 13:03:52 -040078 // The spec document generator uses OptionalOperandLiteral for several kinds
79 // of repeating values. Our parser needs more specific information about
80 // what is being repeated.
81 if (operandClass == OperandOptionalLiteral) {
Lei Zhang40056702015-09-11 14:31:27 -040082 switch (opcode) {
David Neto78c3b432015-08-27 13:03:52 -040083 case spv::OpLoad:
84 case spv::OpStore:
85 case spv::OpCopyMemory:
86 case spv::OpCopyMemorySized:
David Neto3fca4cd2015-09-17 17:39:45 -040087 // Expect an optional mask. When the Aligned bit is set in the mask,
88 // we will later add the expectation of a literal number operand.
89 return SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS;
David Neto78c3b432015-08-27 13:03:52 -040090 case spv::OpExecutionMode:
91 return SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE;
92 default:
93 break;
94 }
Lei Zhangb41d1502015-09-14 15:22:23 -040095 } else if (operandClass == OperandVariableLiterals) {
96 if (opcode == spv::OpConstant || opcode == spv::OpSpecConstant)
97 return SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER;
David Neto78c3b432015-08-27 13:03:52 -040098 }
99
100 switch(operandClass) {
101 case OperandNone: return SPV_OPERAND_TYPE_NONE;
102 case OperandId: return SPV_OPERAND_TYPE_ID;
103 case OperandOptionalId: return SPV_OPERAND_TYPE_OPTIONAL_ID;
104 case OperandOptionalImage: return SPV_OPERAND_TYPE_OPTIONAL_IMAGE; // TODO(dneto): This is variable.
105 case OperandVariableIds: return SPV_OPERAND_TYPE_VARIABLE_ID;
106 case OperandOptionalLiteral: return SPV_OPERAND_TYPE_OPTIONAL_LITERAL;
107 case OperandOptionalLiteralString: return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING;
108 case OperandVariableLiterals: return SPV_OPERAND_TYPE_VARIABLE_LITERAL;
109 case OperandLiteralNumber: return SPV_OPERAND_TYPE_LITERAL_NUMBER;
110 case OperandLiteralString: return SPV_OPERAND_TYPE_LITERAL_STRING;
111 case OperandSource: return SPV_OPERAND_TYPE_SOURCE_LANGUAGE;
112 case OperandExecutionModel: return SPV_OPERAND_TYPE_EXECUTION_MODEL;
113 case OperandAddressing: return SPV_OPERAND_TYPE_ADDRESSING_MODEL;
114 case OperandMemory: return SPV_OPERAND_TYPE_MEMORY_MODEL;
115 case OperandExecutionMode: return SPV_OPERAND_TYPE_EXECUTION_MODE;
116 case OperandStorage: return SPV_OPERAND_TYPE_STORAGE_CLASS;
117 case OperandDimensionality: return SPV_OPERAND_TYPE_DIMENSIONALITY;
118 case OperandSamplerAddressingMode: return SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE;
119 case OperandSamplerFilterMode: return SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE;
David Netob30a0c52015-09-16 15:56:43 -0400120 case OperandSamplerImageFormat: return SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT;
David Neto78c3b432015-08-27 13:03:52 -0400121 case OperandImageChannelOrder: return SPV_OPERAND_TYPE_NONE; //TODO
122 case OperandImageChannelDataType: return SPV_OPERAND_TYPE_NONE; //TODO
123 case OperandImageOperands: return SPV_OPERAND_TYPE_NONE; //TODO
124 case OperandFPFastMath: return SPV_OPERAND_TYPE_FP_FAST_MATH_MODE;
125 case OperandFPRoundingMode: return SPV_OPERAND_TYPE_FP_ROUNDING_MODE;
126 case OperandLinkageType: return SPV_OPERAND_TYPE_LINKAGE_TYPE;
127 case OperandAccessQualifier: return SPV_OPERAND_TYPE_ACCESS_QUALIFIER;
128 case OperandFuncParamAttr: return SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE;
129 case OperandDecoration: return SPV_OPERAND_TYPE_DECORATION;
130 case OperandBuiltIn: return SPV_OPERAND_TYPE_BUILT_IN;
131 case OperandSelect: return SPV_OPERAND_TYPE_SELECTION_CONTROL;
132 case OperandLoop: return SPV_OPERAND_TYPE_LOOP_CONTROL;
133 case OperandFunction: return SPV_OPERAND_TYPE_FUNCTION_CONTROL;
134 case OperandMemorySemantics: return SPV_OPERAND_TYPE_MEMORY_SEMANTICS;
135 case OperandMemoryAccess:
136 // This case does not occur in Rev 31.
David Neto3fca4cd2015-09-17 17:39:45 -0400137 // We expect that it will become SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
David Neto78c3b432015-08-27 13:03:52 -0400138 // and we can remove the special casing above for memory operation
139 // instructions.
140 break;
141 case OperandScope: return SPV_OPERAND_TYPE_EXECUTION_SCOPE;
142 case OperandGroupOperation: return SPV_OPERAND_TYPE_GROUP_OPERATION;
143 case OperandKernelEnqueueFlags: return SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS;
144 case OperandKernelProfilingInfo: return SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO;
145 case OperandCapability: return SPV_OPERAND_TYPE_CAPABILITY;
146
147 // Used by GroupMemberDecorate
148 case OperandVariableIdLiteral: return SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL;
149
150 // Used by Switch
151 case OperandVariableLiteralId: return SPV_OPERAND_TYPE_VARIABLE_LITERAL_ID;
152
153 // These exceptional cases shouldn't occur.
154 case OperandCount:
155 default:
156 break;
157 }
158 assert(0 && "Unexpected operand class");
159 return SPV_OPERAND_TYPE_NONE;
160}
161
Lei Zhanga94701d2015-09-14 10:05:37 -0400162} // anonymous namespace
David Neto78c3b432015-08-27 13:03:52 -0400163
164// Finish populating the opcodeTableEntries array.
165void spvOpcodeTableInitialize() {
166 // Compute the operandTypes field for each entry.
Lei Zhanga94701d2015-09-14 10:05:37 -0400167 for (auto &opcode : opcodeTableEntries) {
David Neto78c3b432015-08-27 13:03:52 -0400168 opcode.numTypes = 0;
169 // Type ID always comes first, if present.
170 if (opcode.hasType)
171 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_ID;
172 // Result ID always comes next, if present
173 if (opcode.hasResult)
174 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_RESULT_ID;
Lei Zhanga94701d2015-09-14 10:05:37 -0400175 const uint16_t maxNumOperands =
176 sizeof(opcode.operandTypes) / sizeof(opcode.operandTypes[0]);
177 const uint16_t maxNumClasses =
178 sizeof(opcode.operandClass) / sizeof(opcode.operandClass[0]);
179 for (uint16_t classIndex = 0;
180 opcode.numTypes < maxNumOperands && classIndex < maxNumClasses;
181 classIndex++) {
David Neto78c3b432015-08-27 13:03:52 -0400182 const OperandClass operandClass = opcode.operandClass[classIndex];
Lei Zhanga94701d2015-09-14 10:05:37 -0400183 opcode.operandTypes[opcode.numTypes++] =
184 convertOperandClassToType(opcode.opcode, operandClass);
David Neto78c3b432015-08-27 13:03:52 -0400185 // The OperandNone value is not explicitly represented in the .inc file.
186 // However, it is the zero value, and is created via implicit value
187 // initialization.
188 if (operandClass == OperandNone) {
189 opcode.numTypes--;
190 break;
191 }
192 }
193 // We should have written the terminating SPV_OPERAND_TYPE_NONE entry, but
194 // also without overflowing.
Lei Zhanga94701d2015-09-14 10:05:37 -0400195 assert((opcode.numTypes < maxNumOperands) &&
196 "Operand class list is too long. Expand "
197 "spv_opcode_desc_t.operandClass");
David Neto78c3b432015-08-27 13:03:52 -0400198 }
199 opcodeTableInitialized = true;
200}
201
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100202const char *spvGeneratorStr(uint32_t generator) {
203 switch (generator) {
204 case SPV_GENERATOR_KHRONOS:
205 return "Khronos";
206 case SPV_GENERATOR_VALVE:
207 return "Valve";
208 case SPV_GENERATOR_LUNARG:
209 return "LunarG";
210 case SPV_GENERATOR_CODEPLAY:
211 return "Codeplay Software Ltd.";
212 default:
213 return "Unknown";
214 }
215}
216
217uint32_t spvOpcodeMake(uint16_t wordCount, Op opcode) {
218 return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
219}
220
221void spvOpcodeSplit(const uint32_t word, uint16_t *pWordCount, Op *pOpcode) {
222 if (pWordCount) {
223 *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
224 }
225 if (pOpcode) {
226 *pOpcode = (Op)(0x0000ffff & word);
227 }
228}
229
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100230spv_result_t spvOpcodeTableGet(spv_opcode_table *pInstTable) {
Lei Zhang40056702015-09-11 14:31:27 -0400231 if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100232
David Neto78c3b432015-08-27 13:03:52 -0400233 static spv_opcode_table_t table = {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100234 sizeof(opcodeTableEntries) / sizeof(spv_opcode_desc_t),
235 opcodeTableEntries};
236
David Neto78c3b432015-08-27 13:03:52 -0400237 // TODO(dneto): Consider thread safety of initialization.
238 // That is, ordering effects of the flag vs. the table updates.
Lei Zhang40056702015-09-11 14:31:27 -0400239 if (!opcodeTableInitialized) spvOpcodeTableInitialize();
David Neto78c3b432015-08-27 13:03:52 -0400240
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100241 *pInstTable = &table;
242
243 return SPV_SUCCESS;
244}
245
246spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
247 const char *name,
248 spv_opcode_desc *pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400249 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
250 if (!table) return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100251
252 // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
253 // preferable but the table requires sorting on the Opcode name, but it's
254 // static
255 // const initialized and matches the order of the spec.
256 const size_t nameLength = strlen(name);
257 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
258 if (nameLength == strlen(table->entries[opcodeIndex].name) &&
259 !strncmp(name, table->entries[opcodeIndex].name, nameLength)) {
260 // NOTE: Found out Opcode!
261 *pEntry = &table->entries[opcodeIndex];
262 return SPV_SUCCESS;
263 }
264 }
265
266 return SPV_ERROR_INVALID_LOOKUP;
267}
268
269spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
270 const Op opcode,
271 spv_opcode_desc *pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400272 if (!table) return SPV_ERROR_INVALID_TABLE;
273 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100274
275 // TODO: As above this lookup is not optimal.
276 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
277 if (opcode == table->entries[opcodeIndex].opcode) {
278 // NOTE: Found the Opcode!
279 *pEntry = &table->entries[opcodeIndex];
280 return SPV_SUCCESS;
281 }
282 }
283
284 return SPV_ERROR_INVALID_LOOKUP;
285}
286
Lei Zhangdfc50082015-08-21 11:50:55 -0400287int16_t spvOpcodeResultIdIndex(spv_opcode_desc entry) {
David Neto78c3b432015-08-27 13:03:52 -0400288 for (int16_t i = 0; i < entry->numTypes; ++i) {
Lei Zhangdfc50082015-08-21 11:50:55 -0400289 if (SPV_OPERAND_TYPE_RESULT_ID == entry->operandTypes[i]) return i;
290 }
291 return SPV_OPERAND_INVALID_RESULT_ID_INDEX;
292}
293
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100294int32_t spvOpcodeRequiresCapabilities(spv_opcode_desc entry) {
295 return SPV_OPCODE_FLAGS_CAPABILITIES ==
296 (SPV_OPCODE_FLAGS_CAPABILITIES & entry->flags);
297}
298
299void spvInstructionCopy(const uint32_t *words, const Op opcode,
300 const uint16_t wordCount, const spv_endianness_t endian,
301 spv_instruction_t *pInst) {
302 pInst->opcode = opcode;
303 pInst->wordCount = wordCount;
304 for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
305 pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
306 if (!wordIndex) {
307 uint16_t thisWordCount;
308 Op thisOpcode;
309 spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
310 assert(opcode == thisOpcode && wordCount == thisWordCount &&
311 "Endianness failed!");
312 }
313 }
314}
315
316const char *spvOpcodeString(const Op opcode) {
317#define CASE(OPCODE) \
318 case OPCODE: \
319 return #OPCODE;
320 switch (opcode) {
321 CASE(OpNop)
322 CASE(OpSource)
323 CASE(OpSourceExtension)
324 CASE(OpExtension)
325 CASE(OpExtInstImport)
326 CASE(OpMemoryModel)
327 CASE(OpEntryPoint)
328 CASE(OpExecutionMode)
329 CASE(OpTypeVoid)
330 CASE(OpTypeBool)
331 CASE(OpTypeInt)
332 CASE(OpTypeFloat)
333 CASE(OpTypeVector)
334 CASE(OpTypeMatrix)
335 CASE(OpTypeSampler)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100336 CASE(OpTypeArray)
337 CASE(OpTypeRuntimeArray)
338 CASE(OpTypeStruct)
339 CASE(OpTypeOpaque)
340 CASE(OpTypePointer)
341 CASE(OpTypeFunction)
342 CASE(OpTypeEvent)
343 CASE(OpTypeDeviceEvent)
344 CASE(OpTypeReserveId)
345 CASE(OpTypeQueue)
346 CASE(OpTypePipe)
347 CASE(OpConstantTrue)
348 CASE(OpConstantFalse)
349 CASE(OpConstant)
350 CASE(OpConstantComposite)
351 CASE(OpConstantSampler)
352 CASE(OpConstantNull)
353 CASE(OpSpecConstantTrue)
354 CASE(OpSpecConstantFalse)
355 CASE(OpSpecConstant)
356 CASE(OpSpecConstantComposite)
357 CASE(OpVariable)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100358 CASE(OpFunction)
359 CASE(OpFunctionParameter)
360 CASE(OpFunctionEnd)
361 CASE(OpFunctionCall)
362 CASE(OpExtInst)
363 CASE(OpUndef)
364 CASE(OpLoad)
365 CASE(OpStore)
366 CASE(OpPhi)
367 CASE(OpDecorationGroup)
368 CASE(OpDecorate)
369 CASE(OpMemberDecorate)
370 CASE(OpGroupDecorate)
371 CASE(OpGroupMemberDecorate)
372 CASE(OpName)
373 CASE(OpMemberName)
374 CASE(OpString)
375 CASE(OpLine)
376 CASE(OpVectorExtractDynamic)
377 CASE(OpVectorInsertDynamic)
378 CASE(OpVectorShuffle)
379 CASE(OpCompositeConstruct)
380 CASE(OpCompositeExtract)
381 CASE(OpCompositeInsert)
382 CASE(OpCopyObject)
383 CASE(OpCopyMemory)
384 CASE(OpCopyMemorySized)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100385 CASE(OpAccessChain)
386 CASE(OpInBoundsAccessChain)
387 CASE(OpSNegate)
388 CASE(OpFNegate)
389 CASE(OpNot)
390 CASE(OpAny)
391 CASE(OpAll)
392 CASE(OpConvertFToU)
393 CASE(OpConvertFToS)
394 CASE(OpConvertSToF)
395 CASE(OpConvertUToF)
396 CASE(OpUConvert)
397 CASE(OpSConvert)
398 CASE(OpFConvert)
399 CASE(OpConvertPtrToU)
400 CASE(OpConvertUToPtr)
401 CASE(OpPtrCastToGeneric)
402 CASE(OpGenericCastToPtr)
403 CASE(OpBitcast)
404 CASE(OpTranspose)
405 CASE(OpIsNan)
406 CASE(OpIsInf)
407 CASE(OpIsFinite)
408 CASE(OpIsNormal)
409 CASE(OpSignBitSet)
410 CASE(OpLessOrGreater)
411 CASE(OpOrdered)
412 CASE(OpUnordered)
413 CASE(OpArrayLength)
414 CASE(OpIAdd)
415 CASE(OpFAdd)
416 CASE(OpISub)
417 CASE(OpFSub)
418 CASE(OpIMul)
419 CASE(OpFMul)
420 CASE(OpUDiv)
421 CASE(OpSDiv)
422 CASE(OpFDiv)
423 CASE(OpUMod)
424 CASE(OpSRem)
425 CASE(OpSMod)
426 CASE(OpFRem)
427 CASE(OpFMod)
428 CASE(OpVectorTimesScalar)
429 CASE(OpMatrixTimesScalar)
430 CASE(OpVectorTimesMatrix)
431 CASE(OpMatrixTimesVector)
432 CASE(OpMatrixTimesMatrix)
433 CASE(OpOuterProduct)
434 CASE(OpDot)
435 CASE(OpShiftRightLogical)
436 CASE(OpShiftRightArithmetic)
437 CASE(OpShiftLeftLogical)
438 CASE(OpLogicalOr)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100439 CASE(OpLogicalAnd)
440 CASE(OpBitwiseOr)
441 CASE(OpBitwiseXor)
442 CASE(OpBitwiseAnd)
443 CASE(OpSelect)
444 CASE(OpIEqual)
445 CASE(OpFOrdEqual)
446 CASE(OpFUnordEqual)
447 CASE(OpINotEqual)
448 CASE(OpFOrdNotEqual)
449 CASE(OpFUnordNotEqual)
450 CASE(OpULessThan)
451 CASE(OpSLessThan)
452 CASE(OpFOrdLessThan)
453 CASE(OpFUnordLessThan)
454 CASE(OpUGreaterThan)
455 CASE(OpSGreaterThan)
456 CASE(OpFOrdGreaterThan)
457 CASE(OpFUnordGreaterThan)
458 CASE(OpULessThanEqual)
459 CASE(OpSLessThanEqual)
460 CASE(OpFOrdLessThanEqual)
461 CASE(OpFUnordLessThanEqual)
462 CASE(OpUGreaterThanEqual)
463 CASE(OpSGreaterThanEqual)
464 CASE(OpFOrdGreaterThanEqual)
465 CASE(OpFUnordGreaterThanEqual)
466 CASE(OpDPdx)
467 CASE(OpDPdy)
468 CASE(OpFwidth)
469 CASE(OpDPdxFine)
470 CASE(OpDPdyFine)
471 CASE(OpFwidthFine)
472 CASE(OpDPdxCoarse)
473 CASE(OpDPdyCoarse)
474 CASE(OpFwidthCoarse)
475 CASE(OpEmitVertex)
476 CASE(OpEndPrimitive)
477 CASE(OpEmitStreamVertex)
478 CASE(OpEndStreamPrimitive)
479 CASE(OpControlBarrier)
480 CASE(OpMemoryBarrier)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100481 CASE(OpAtomicLoad)
482 CASE(OpAtomicStore)
483 CASE(OpAtomicExchange)
484 CASE(OpAtomicCompareExchange)
485 CASE(OpAtomicCompareExchangeWeak)
486 CASE(OpAtomicIIncrement)
487 CASE(OpAtomicIDecrement)
488 CASE(OpAtomicIAdd)
489 CASE(OpAtomicISub)
490 CASE(OpAtomicUMin)
491 CASE(OpAtomicUMax)
492 CASE(OpAtomicAnd)
493 CASE(OpAtomicOr)
494 CASE(OpAtomicXor)
495 CASE(OpLoopMerge)
496 CASE(OpSelectionMerge)
497 CASE(OpLabel)
498 CASE(OpBranch)
499 CASE(OpBranchConditional)
500 CASE(OpSwitch)
501 CASE(OpKill)
502 CASE(OpReturn)
503 CASE(OpReturnValue)
504 CASE(OpUnreachable)
505 CASE(OpLifetimeStart)
506 CASE(OpLifetimeStop)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100507 CASE(OpAsyncGroupCopy)
508 CASE(OpWaitGroupEvents)
509 CASE(OpGroupAll)
510 CASE(OpGroupAny)
511 CASE(OpGroupBroadcast)
512 CASE(OpGroupIAdd)
513 CASE(OpGroupFAdd)
514 CASE(OpGroupFMin)
515 CASE(OpGroupUMin)
516 CASE(OpGroupSMin)
517 CASE(OpGroupFMax)
518 CASE(OpGroupUMax)
519 CASE(OpGroupSMax)
520 CASE(OpGenericCastToPtrExplicit)
521 CASE(OpGenericPtrMemSemantics)
522 CASE(OpReadPipe)
523 CASE(OpWritePipe)
524 CASE(OpReservedReadPipe)
525 CASE(OpReservedWritePipe)
526 CASE(OpReserveReadPipePackets)
527 CASE(OpReserveWritePipePackets)
528 CASE(OpCommitReadPipe)
529 CASE(OpCommitWritePipe)
530 CASE(OpIsValidReserveId)
531 CASE(OpGetNumPipePackets)
532 CASE(OpGetMaxPipePackets)
533 CASE(OpGroupReserveReadPipePackets)
534 CASE(OpGroupReserveWritePipePackets)
535 CASE(OpGroupCommitReadPipe)
536 CASE(OpGroupCommitWritePipe)
537 CASE(OpEnqueueMarker)
538 CASE(OpEnqueueKernel)
539 CASE(OpGetKernelNDrangeSubGroupCount)
540 CASE(OpGetKernelNDrangeMaxSubGroupSize)
541 CASE(OpGetKernelWorkGroupSize)
542 CASE(OpGetKernelPreferredWorkGroupSizeMultiple)
543 CASE(OpRetainEvent)
544 CASE(OpReleaseEvent)
545 CASE(OpCreateUserEvent)
546 CASE(OpIsValidEvent)
547 CASE(OpSetUserEventStatus)
548 CASE(OpCaptureEventProfilingInfo)
549 CASE(OpGetDefaultQueue)
550 CASE(OpBuildNDRange)
551 default:
552 assert(0 && "Unreachable!");
553 }
554#undef CASE
555 return "unknown";
556}
557
558int32_t spvOpcodeIsType(const Op opcode) {
559 switch (opcode) {
560 case OpTypeVoid:
561 case OpTypeBool:
562 case OpTypeInt:
563 case OpTypeFloat:
564 case OpTypeVector:
565 case OpTypeMatrix:
566 case OpTypeSampler:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100567 case OpTypeArray:
568 case OpTypeRuntimeArray:
569 case OpTypeStruct:
570 case OpTypeOpaque:
571 case OpTypePointer:
572 case OpTypeFunction:
573 case OpTypeEvent:
574 case OpTypeDeviceEvent:
575 case OpTypeReserveId:
576 case OpTypeQueue:
577 case OpTypePipe:
578 return true;
579 default:
580 return false;
581 }
582}
583
584int32_t spvOpcodeIsScalarType(const Op opcode) {
585 switch (opcode) {
586 case OpTypeInt:
587 case OpTypeFloat:
588 return true;
589 default:
590 return false;
591 }
592}
593
594int32_t spvOpcodeIsConstant(const Op opcode) {
595 switch (opcode) {
596 case OpConstantTrue:
597 case OpConstantFalse:
598 case OpConstant:
599 case OpConstantComposite:
600 case OpConstantSampler:
601 // case OpConstantNull:
602 case OpConstantNull:
603 case OpSpecConstantTrue:
604 case OpSpecConstantFalse:
605 case OpSpecConstant:
606 case OpSpecConstantComposite:
607 // case OpSpecConstantOp:
608 return true;
609 default:
610 return false;
611 }
612}
613
614int32_t spvOpcodeIsComposite(const Op opcode) {
615 switch (opcode) {
616 case OpTypeVector:
617 case OpTypeMatrix:
618 case OpTypeArray:
619 case OpTypeStruct:
620 return true;
621 default:
622 return false;
623 }
624}
625
626int32_t spvOpcodeAreTypesEqual(const spv_instruction_t *pTypeInst0,
627 const spv_instruction_t *pTypeInst1) {
Lei Zhang40056702015-09-11 14:31:27 -0400628 if (pTypeInst0->opcode != pTypeInst1->opcode) return false;
629 if (pTypeInst0->words[1] != pTypeInst1->words[1]) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100630 return true;
631}
632
633int32_t spvOpcodeIsPointer(const Op opcode) {
634 switch (opcode) {
635 case OpVariable:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100636 case OpAccessChain:
637 case OpInBoundsAccessChain:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100638 case OpFunctionParameter:
639 return true;
640 default:
641 return false;
642 }
643}
644
645int32_t spvOpcodeIsObject(const Op opcode) {
646 switch (opcode) {
647 case OpConstantTrue:
648 case OpConstantFalse:
649 case OpConstant:
650 case OpConstantComposite:
651 // TODO: case OpConstantSampler:
652 case OpConstantNull:
653 case OpSpecConstantTrue:
654 case OpSpecConstantFalse:
655 case OpSpecConstant:
656 case OpSpecConstantComposite:
657 // TODO: case OpSpecConstantOp:
658 case OpVariable:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100659 case OpAccessChain:
660 case OpInBoundsAccessChain:
661 case OpConvertFToU:
662 case OpConvertFToS:
663 case OpConvertSToF:
664 case OpConvertUToF:
665 case OpUConvert:
666 case OpSConvert:
667 case OpFConvert:
668 case OpConvertPtrToU:
669 // TODO: case OpConvertUToPtr:
670 case OpPtrCastToGeneric:
671 // TODO: case OpGenericCastToPtr:
672 case OpBitcast:
673 // TODO: case OpGenericCastToPtrExplicit:
674 case OpSatConvertSToU:
675 case OpSatConvertUToS:
676 case OpVectorExtractDynamic:
677 case OpCompositeConstruct:
678 case OpCompositeExtract:
679 case OpCopyObject:
680 case OpTranspose:
681 case OpSNegate:
682 case OpFNegate:
683 case OpNot:
684 case OpIAdd:
685 case OpFAdd:
686 case OpISub:
687 case OpFSub:
688 case OpIMul:
689 case OpFMul:
690 case OpUDiv:
691 case OpSDiv:
692 case OpFDiv:
693 case OpUMod:
694 case OpSRem:
695 case OpSMod:
696 case OpVectorTimesScalar:
697 case OpMatrixTimesScalar:
698 case OpVectorTimesMatrix:
699 case OpMatrixTimesVector:
700 case OpMatrixTimesMatrix:
701 case OpOuterProduct:
702 case OpDot:
703 case OpShiftRightLogical:
704 case OpShiftRightArithmetic:
705 case OpShiftLeftLogical:
706 case OpBitwiseOr:
707 case OpBitwiseXor:
708 case OpBitwiseAnd:
709 case OpAny:
710 case OpAll:
711 case OpIsNan:
712 case OpIsInf:
713 case OpIsFinite:
714 case OpIsNormal:
715 case OpSignBitSet:
716 case OpLessOrGreater:
717 case OpOrdered:
718 case OpUnordered:
719 case OpLogicalOr:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100720 case OpLogicalAnd:
721 case OpSelect:
722 case OpIEqual:
723 case OpFOrdEqual:
724 case OpFUnordEqual:
725 case OpINotEqual:
726 case OpFOrdNotEqual:
727 case OpFUnordNotEqual:
728 case OpULessThan:
729 case OpSLessThan:
730 case OpFOrdLessThan:
731 case OpFUnordLessThan:
732 case OpUGreaterThan:
733 case OpSGreaterThan:
734 case OpFOrdGreaterThan:
735 case OpFUnordGreaterThan:
736 case OpULessThanEqual:
737 case OpSLessThanEqual:
738 case OpFOrdLessThanEqual:
739 case OpFUnordLessThanEqual:
740 case OpUGreaterThanEqual:
741 case OpSGreaterThanEqual:
742 case OpFOrdGreaterThanEqual:
743 case OpFUnordGreaterThanEqual:
744 case OpDPdx:
745 case OpDPdy:
746 case OpFwidth:
747 case OpDPdxFine:
748 case OpDPdyFine:
749 case OpFwidthFine:
750 case OpDPdxCoarse:
751 case OpDPdyCoarse:
752 case OpFwidthCoarse:
753 case OpReturnValue:
754 return true;
755 default:
756 return false;
757 }
758}
759
760int32_t spvOpcodeIsBasicTypeNullable(Op opcode) {
761 switch (opcode) {
762 case OpTypeBool:
763 case OpTypeInt:
764 case OpTypeFloat:
765 case OpTypePointer:
766 case OpTypeEvent:
767 case OpTypeDeviceEvent:
768 case OpTypeReserveId:
769 case OpTypeQueue:
770 return true;
771 default:
772 return false;
773 }
774}
775
776int32_t spvInstructionIsInBasicBlock(const spv_instruction_t *pFirstInst,
777 const spv_instruction_t *pInst) {
778 while (pFirstInst != pInst) {
Lei Zhang40056702015-09-11 14:31:27 -0400779 if (OpFunction == pInst->opcode) break;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100780 pInst--;
781 }
Lei Zhang40056702015-09-11 14:31:27 -0400782 if (OpFunction != pInst->opcode) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100783 return true;
784}
785
786int32_t spvOpcodeIsValue(Op opcode) {
Lei Zhang40056702015-09-11 14:31:27 -0400787 if (spvOpcodeIsPointer(opcode)) return true;
788 if (spvOpcodeIsConstant(opcode)) return true;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100789 switch (opcode) {
790 case OpLoad:
791 // TODO: Other Opcode's resulting in a value
792 return true;
793 default:
794 return false;
795 }
796}