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