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