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