blob: d30d356a16b0b469bbeb36590db174377146c5b7 [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"
David Netob5dc8fc2015-10-06 16:22:00 -040029#include "instruction.h"
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010030#include "opcode.h"
31
32#include <assert.h>
33#include <string.h>
34
David Neto78c3b432015-08-27 13:03:52 -040035namespace {
36
37// Descriptions of each opcode. Each entry describes the format of the
38// instruction that follows a particular opcode.
39//
40// Most fields are initialized statically by including an automatically
41// generated file.
42// The operandTypes fields are initialized during spvOpcodeInitialize().
43//
44// TODO(dneto): Some of the macros are quite unreadable. We could make
45// good use of constexpr functions, but some compilers don't support that yet.
46spv_opcode_desc_t opcodeTableEntries[] = {
47#define EmptyList {}
48#define List(...) {__VA_ARGS__}
Dejan Mircevski205408b2015-09-30 16:42:34 -040049#define Capability(X) SPV_CAPABILITY_AS_MASK(Capability##X)
50#define Capability2(X,Y) Capability(X)|Capability(Y)
51#define CapabilityNone 0 // Needed so Capability(None) still expands to valid syntax.
David Neto78c3b432015-08-27 13:03:52 -040052#define Instruction(Name,HasResult,HasType,NumLogicalOperands,NumCapabilities,CapabilityRequired,IsVariable,LogicalArgsList) \
53 { #Name, \
54 Op##Name, \
Dejan Mircevski205408b2015-09-30 16:42:34 -040055 (NumCapabilities) ? (CapabilityRequired) : 0, \
David Neto78c3b432015-08-27 13:03:52 -040056 0, {}, /* Filled in later. Operand list, including result id and type id, if needed */ \
57 HasResult, \
58 HasType, \
59 LogicalArgsList },
60#include "opcode.inc"
61#undef EmptyList
62#undef List
63#undef Capability
Dejan Mircevski205408b2015-09-30 16:42:34 -040064#undef Capability2
David Neto78c3b432015-08-27 13:03:52 -040065#undef CapabilityNone
66#undef Instruction
67};
68
69// Has the opcodeTableEntries table been fully elaborated?
70// That is, are the operandTypes fields initialized?
71bool opcodeTableInitialized = false;
72
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010073// Opcode API
74
David Neto78c3b432015-08-27 13:03:52 -040075// Converts the given operand class enum (from the SPIR-V document generation
76// logic) to the operand type required by the parser.
77// This only applies to logical operands.
Lei Zhang40056702015-09-11 14:31:27 -040078spv_operand_type_t convertOperandClassToType(spv::Op opcode,
79 spv::OperandClass operandClass) {
David Neto78c3b432015-08-27 13:03:52 -040080 // The spec document generator uses OptionalOperandLiteral for several kinds
81 // of repeating values. Our parser needs more specific information about
82 // what is being repeated.
83 if (operandClass == OperandOptionalLiteral) {
Lei Zhang40056702015-09-11 14:31:27 -040084 switch (opcode) {
David Neto78c3b432015-08-27 13:03:52 -040085 case spv::OpLoad:
86 case spv::OpStore:
87 case spv::OpCopyMemory:
88 case spv::OpCopyMemorySized:
David Neto3fca4cd2015-09-17 17:39:45 -040089 // Expect an optional mask. When the Aligned bit is set in the mask,
90 // we will later add the expectation of a literal number operand.
91 return SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS;
David Neto78c3b432015-08-27 13:03:52 -040092 case spv::OpExecutionMode:
93 return SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE;
94 default:
95 break;
96 }
Lei Zhangb41d1502015-09-14 15:22:23 -040097 } else if (operandClass == OperandVariableLiterals) {
98 if (opcode == spv::OpConstant || opcode == spv::OpSpecConstant)
99 return SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER;
David Neto78c3b432015-08-27 13:03:52 -0400100 }
101
102 switch(operandClass) {
103 case OperandNone: return SPV_OPERAND_TYPE_NONE;
104 case OperandId: return SPV_OPERAND_TYPE_ID;
105 case OperandOptionalId: return SPV_OPERAND_TYPE_OPTIONAL_ID;
David Neto561dc4e2015-09-25 14:23:29 -0400106 case OperandOptionalImage: return SPV_OPERAND_TYPE_OPTIONAL_IMAGE;
David Neto78c3b432015-08-27 13:03:52 -0400107 case OperandVariableIds: return SPV_OPERAND_TYPE_VARIABLE_ID;
David Neto561dc4e2015-09-25 14:23:29 -0400108 // The spec only uses OptionalLiteral for an optional literal number.
109 case OperandOptionalLiteral: return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER;
David Neto78c3b432015-08-27 13:03:52 -0400110 case OperandOptionalLiteralString: return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING;
David Neto561dc4e2015-09-25 14:23:29 -0400111 // This is only used for sequences of literal numbers.
112 case OperandVariableLiterals: return SPV_OPERAND_TYPE_VARIABLE_LITERAL_NUMBER;
David Neto78c3b432015-08-27 13:03:52 -0400113 case OperandLiteralNumber: return SPV_OPERAND_TYPE_LITERAL_NUMBER;
114 case OperandLiteralString: return SPV_OPERAND_TYPE_LITERAL_STRING;
115 case OperandSource: return SPV_OPERAND_TYPE_SOURCE_LANGUAGE;
116 case OperandExecutionModel: return SPV_OPERAND_TYPE_EXECUTION_MODEL;
117 case OperandAddressing: return SPV_OPERAND_TYPE_ADDRESSING_MODEL;
118 case OperandMemory: return SPV_OPERAND_TYPE_MEMORY_MODEL;
119 case OperandExecutionMode: return SPV_OPERAND_TYPE_EXECUTION_MODE;
120 case OperandStorage: return SPV_OPERAND_TYPE_STORAGE_CLASS;
121 case OperandDimensionality: return SPV_OPERAND_TYPE_DIMENSIONALITY;
122 case OperandSamplerAddressingMode: return SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE;
123 case OperandSamplerFilterMode: return SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE;
David Netob30a0c52015-09-16 15:56:43 -0400124 case OperandSamplerImageFormat: return SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT;
David Neto7cefb232015-09-28 15:33:49 -0400125 case OperandImageChannelOrder:
126 // This is only used to describe the value generated by OpImageQueryOrder.
127 // It is not used as an operand.
128 break;
129 case OperandImageChannelDataType:
130 // This is only used to describe the value generated by OpImageQueryFormat.
131 // It is not used as an operand.
132 break;
133 case OperandImageOperands:
Dejan Mircevskif8e091a2015-10-13 14:41:31 -0400134 // This is not used in opcode.inc. It only exists to generate the
135 // corresponding spec section. In parsing, image operands meld into the
136 // OperandOptionalImage case.
David Neto7cefb232015-09-28 15:33:49 -0400137 break;
David Neto78c3b432015-08-27 13:03:52 -0400138 case OperandFPFastMath: return SPV_OPERAND_TYPE_FP_FAST_MATH_MODE;
139 case OperandFPRoundingMode: return SPV_OPERAND_TYPE_FP_ROUNDING_MODE;
140 case OperandLinkageType: return SPV_OPERAND_TYPE_LINKAGE_TYPE;
141 case OperandAccessQualifier: return SPV_OPERAND_TYPE_ACCESS_QUALIFIER;
142 case OperandFuncParamAttr: return SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE;
143 case OperandDecoration: return SPV_OPERAND_TYPE_DECORATION;
144 case OperandBuiltIn: return SPV_OPERAND_TYPE_BUILT_IN;
145 case OperandSelect: return SPV_OPERAND_TYPE_SELECTION_CONTROL;
146 case OperandLoop: return SPV_OPERAND_TYPE_LOOP_CONTROL;
147 case OperandFunction: return SPV_OPERAND_TYPE_FUNCTION_CONTROL;
148 case OperandMemorySemantics: return SPV_OPERAND_TYPE_MEMORY_SEMANTICS;
149 case OperandMemoryAccess:
David Neto7cefb232015-09-28 15:33:49 -0400150 // This case does not occur in the table for SPIR-V 0.99 Rev 32.
David Neto3fca4cd2015-09-17 17:39:45 -0400151 // We expect that it will become SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
David Neto78c3b432015-08-27 13:03:52 -0400152 // and we can remove the special casing above for memory operation
153 // instructions.
154 break;
155 case OperandScope: return SPV_OPERAND_TYPE_EXECUTION_SCOPE;
156 case OperandGroupOperation: return SPV_OPERAND_TYPE_GROUP_OPERATION;
157 case OperandKernelEnqueueFlags: return SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS;
158 case OperandKernelProfilingInfo: return SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO;
159 case OperandCapability: return SPV_OPERAND_TYPE_CAPABILITY;
160
161 // Used by GroupMemberDecorate
David Neto561dc4e2015-09-25 14:23:29 -0400162 case OperandVariableIdLiteral: return SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_NUMBER;
David Neto78c3b432015-08-27 13:03:52 -0400163
164 // Used by Switch
David Neto561dc4e2015-09-25 14:23:29 -0400165 case OperandVariableLiteralId: return SPV_OPERAND_TYPE_VARIABLE_LITERAL_NUMBER_ID;
David Neto78c3b432015-08-27 13:03:52 -0400166
167 // These exceptional cases shouldn't occur.
168 case OperandCount:
169 default:
170 break;
171 }
172 assert(0 && "Unexpected operand class");
173 return SPV_OPERAND_TYPE_NONE;
174}
175
Lei Zhanga94701d2015-09-14 10:05:37 -0400176} // anonymous namespace
David Neto78c3b432015-08-27 13:03:52 -0400177
178// Finish populating the opcodeTableEntries array.
179void spvOpcodeTableInitialize() {
180 // Compute the operandTypes field for each entry.
Lei Zhanga94701d2015-09-14 10:05:37 -0400181 for (auto &opcode : opcodeTableEntries) {
David Neto78c3b432015-08-27 13:03:52 -0400182 opcode.numTypes = 0;
183 // Type ID always comes first, if present.
184 if (opcode.hasType)
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400185 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_TYPE_ID;
David Neto78c3b432015-08-27 13:03:52 -0400186 // Result ID always comes next, if present
187 if (opcode.hasResult)
188 opcode.operandTypes[opcode.numTypes++] = SPV_OPERAND_TYPE_RESULT_ID;
Lei Zhanga94701d2015-09-14 10:05:37 -0400189 const uint16_t maxNumOperands =
190 sizeof(opcode.operandTypes) / sizeof(opcode.operandTypes[0]);
191 const uint16_t maxNumClasses =
192 sizeof(opcode.operandClass) / sizeof(opcode.operandClass[0]);
193 for (uint16_t classIndex = 0;
194 opcode.numTypes < maxNumOperands && classIndex < maxNumClasses;
195 classIndex++) {
David Neto78c3b432015-08-27 13:03:52 -0400196 const OperandClass operandClass = opcode.operandClass[classIndex];
Lei Zhanga94701d2015-09-14 10:05:37 -0400197 opcode.operandTypes[opcode.numTypes++] =
198 convertOperandClassToType(opcode.opcode, operandClass);
David Neto78c3b432015-08-27 13:03:52 -0400199 // The OperandNone value is not explicitly represented in the .inc file.
200 // However, it is the zero value, and is created via implicit value
201 // initialization.
202 if (operandClass == OperandNone) {
203 opcode.numTypes--;
204 break;
205 }
206 }
207 // We should have written the terminating SPV_OPERAND_TYPE_NONE entry, but
208 // also without overflowing.
Lei Zhanga94701d2015-09-14 10:05:37 -0400209 assert((opcode.numTypes < maxNumOperands) &&
210 "Operand class list is too long. Expand "
211 "spv_opcode_desc_t.operandClass");
David Neto78c3b432015-08-27 13:03:52 -0400212 }
213 opcodeTableInitialized = true;
214}
215
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100216const char *spvGeneratorStr(uint32_t generator) {
217 switch (generator) {
218 case SPV_GENERATOR_KHRONOS:
219 return "Khronos";
220 case SPV_GENERATOR_VALVE:
221 return "Valve";
222 case SPV_GENERATOR_LUNARG:
223 return "LunarG";
224 case SPV_GENERATOR_CODEPLAY:
225 return "Codeplay Software Ltd.";
226 default:
227 return "Unknown";
228 }
229}
230
231uint32_t spvOpcodeMake(uint16_t wordCount, Op opcode) {
232 return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
233}
234
235void spvOpcodeSplit(const uint32_t word, uint16_t *pWordCount, Op *pOpcode) {
236 if (pWordCount) {
237 *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
238 }
239 if (pOpcode) {
240 *pOpcode = (Op)(0x0000ffff & word);
241 }
242}
243
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100244spv_result_t spvOpcodeTableGet(spv_opcode_table *pInstTable) {
Lei Zhang40056702015-09-11 14:31:27 -0400245 if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100246
David Neto78c3b432015-08-27 13:03:52 -0400247 static spv_opcode_table_t table = {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100248 sizeof(opcodeTableEntries) / sizeof(spv_opcode_desc_t),
249 opcodeTableEntries};
250
David Neto78c3b432015-08-27 13:03:52 -0400251 // TODO(dneto): Consider thread safety of initialization.
252 // That is, ordering effects of the flag vs. the table updates.
Lei Zhang40056702015-09-11 14:31:27 -0400253 if (!opcodeTableInitialized) spvOpcodeTableInitialize();
David Neto78c3b432015-08-27 13:03:52 -0400254
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100255 *pInstTable = &table;
256
257 return SPV_SUCCESS;
258}
259
260spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
261 const char *name,
262 spv_opcode_desc *pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400263 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
264 if (!table) return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100265
266 // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
267 // preferable but the table requires sorting on the Opcode name, but it's
268 // static
269 // const initialized and matches the order of the spec.
270 const size_t nameLength = strlen(name);
271 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
272 if (nameLength == strlen(table->entries[opcodeIndex].name) &&
273 !strncmp(name, table->entries[opcodeIndex].name, nameLength)) {
274 // NOTE: Found out Opcode!
275 *pEntry = &table->entries[opcodeIndex];
276 return SPV_SUCCESS;
277 }
278 }
279
280 return SPV_ERROR_INVALID_LOOKUP;
281}
282
283spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
284 const Op opcode,
285 spv_opcode_desc *pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400286 if (!table) return SPV_ERROR_INVALID_TABLE;
287 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100288
289 // TODO: As above this lookup is not optimal.
290 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
291 if (opcode == table->entries[opcodeIndex].opcode) {
292 // NOTE: Found the Opcode!
293 *pEntry = &table->entries[opcodeIndex];
294 return SPV_SUCCESS;
295 }
296 }
297
298 return SPV_ERROR_INVALID_LOOKUP;
299}
300
Lei Zhangdfc50082015-08-21 11:50:55 -0400301int16_t spvOpcodeResultIdIndex(spv_opcode_desc entry) {
David Neto78c3b432015-08-27 13:03:52 -0400302 for (int16_t i = 0; i < entry->numTypes; ++i) {
Lei Zhangdfc50082015-08-21 11:50:55 -0400303 if (SPV_OPERAND_TYPE_RESULT_ID == entry->operandTypes[i]) return i;
304 }
305 return SPV_OPERAND_INVALID_RESULT_ID_INDEX;
306}
307
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100308int32_t spvOpcodeRequiresCapabilities(spv_opcode_desc entry) {
David Neto9db3a532015-10-07 16:58:38 -0400309 return entry->capabilities != 0;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100310}
311
312void spvInstructionCopy(const uint32_t *words, const Op opcode,
313 const uint16_t wordCount, const spv_endianness_t endian,
314 spv_instruction_t *pInst) {
315 pInst->opcode = opcode;
David Netob5dc8fc2015-10-06 16:22:00 -0400316 pInst->words.resize(wordCount);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100317 for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
318 pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
319 if (!wordIndex) {
320 uint16_t thisWordCount;
321 Op thisOpcode;
322 spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
323 assert(opcode == thisOpcode && wordCount == thisWordCount &&
324 "Endianness failed!");
325 }
326 }
327}
328
329const char *spvOpcodeString(const Op opcode) {
330#define CASE(OPCODE) \
331 case OPCODE: \
332 return #OPCODE;
333 switch (opcode) {
334 CASE(OpNop)
335 CASE(OpSource)
336 CASE(OpSourceExtension)
337 CASE(OpExtension)
338 CASE(OpExtInstImport)
339 CASE(OpMemoryModel)
340 CASE(OpEntryPoint)
341 CASE(OpExecutionMode)
342 CASE(OpTypeVoid)
343 CASE(OpTypeBool)
344 CASE(OpTypeInt)
345 CASE(OpTypeFloat)
346 CASE(OpTypeVector)
347 CASE(OpTypeMatrix)
348 CASE(OpTypeSampler)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100349 CASE(OpTypeArray)
350 CASE(OpTypeRuntimeArray)
351 CASE(OpTypeStruct)
352 CASE(OpTypeOpaque)
353 CASE(OpTypePointer)
354 CASE(OpTypeFunction)
355 CASE(OpTypeEvent)
356 CASE(OpTypeDeviceEvent)
357 CASE(OpTypeReserveId)
358 CASE(OpTypeQueue)
359 CASE(OpTypePipe)
360 CASE(OpConstantTrue)
361 CASE(OpConstantFalse)
362 CASE(OpConstant)
363 CASE(OpConstantComposite)
364 CASE(OpConstantSampler)
365 CASE(OpConstantNull)
366 CASE(OpSpecConstantTrue)
367 CASE(OpSpecConstantFalse)
368 CASE(OpSpecConstant)
369 CASE(OpSpecConstantComposite)
370 CASE(OpVariable)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100371 CASE(OpFunction)
372 CASE(OpFunctionParameter)
373 CASE(OpFunctionEnd)
374 CASE(OpFunctionCall)
375 CASE(OpExtInst)
376 CASE(OpUndef)
377 CASE(OpLoad)
378 CASE(OpStore)
379 CASE(OpPhi)
380 CASE(OpDecorationGroup)
381 CASE(OpDecorate)
382 CASE(OpMemberDecorate)
383 CASE(OpGroupDecorate)
384 CASE(OpGroupMemberDecorate)
385 CASE(OpName)
386 CASE(OpMemberName)
387 CASE(OpString)
388 CASE(OpLine)
389 CASE(OpVectorExtractDynamic)
390 CASE(OpVectorInsertDynamic)
391 CASE(OpVectorShuffle)
392 CASE(OpCompositeConstruct)
393 CASE(OpCompositeExtract)
394 CASE(OpCompositeInsert)
395 CASE(OpCopyObject)
396 CASE(OpCopyMemory)
397 CASE(OpCopyMemorySized)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100398 CASE(OpAccessChain)
399 CASE(OpInBoundsAccessChain)
400 CASE(OpSNegate)
401 CASE(OpFNegate)
402 CASE(OpNot)
403 CASE(OpAny)
404 CASE(OpAll)
405 CASE(OpConvertFToU)
406 CASE(OpConvertFToS)
407 CASE(OpConvertSToF)
408 CASE(OpConvertUToF)
409 CASE(OpUConvert)
410 CASE(OpSConvert)
411 CASE(OpFConvert)
412 CASE(OpConvertPtrToU)
413 CASE(OpConvertUToPtr)
414 CASE(OpPtrCastToGeneric)
415 CASE(OpGenericCastToPtr)
416 CASE(OpBitcast)
417 CASE(OpTranspose)
418 CASE(OpIsNan)
419 CASE(OpIsInf)
420 CASE(OpIsFinite)
421 CASE(OpIsNormal)
422 CASE(OpSignBitSet)
423 CASE(OpLessOrGreater)
424 CASE(OpOrdered)
425 CASE(OpUnordered)
426 CASE(OpArrayLength)
427 CASE(OpIAdd)
428 CASE(OpFAdd)
429 CASE(OpISub)
430 CASE(OpFSub)
431 CASE(OpIMul)
432 CASE(OpFMul)
433 CASE(OpUDiv)
434 CASE(OpSDiv)
435 CASE(OpFDiv)
436 CASE(OpUMod)
437 CASE(OpSRem)
438 CASE(OpSMod)
439 CASE(OpFRem)
440 CASE(OpFMod)
441 CASE(OpVectorTimesScalar)
442 CASE(OpMatrixTimesScalar)
443 CASE(OpVectorTimesMatrix)
444 CASE(OpMatrixTimesVector)
445 CASE(OpMatrixTimesMatrix)
446 CASE(OpOuterProduct)
447 CASE(OpDot)
448 CASE(OpShiftRightLogical)
449 CASE(OpShiftRightArithmetic)
450 CASE(OpShiftLeftLogical)
451 CASE(OpLogicalOr)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100452 CASE(OpLogicalAnd)
453 CASE(OpBitwiseOr)
454 CASE(OpBitwiseXor)
455 CASE(OpBitwiseAnd)
456 CASE(OpSelect)
457 CASE(OpIEqual)
458 CASE(OpFOrdEqual)
459 CASE(OpFUnordEqual)
460 CASE(OpINotEqual)
461 CASE(OpFOrdNotEqual)
462 CASE(OpFUnordNotEqual)
463 CASE(OpULessThan)
464 CASE(OpSLessThan)
465 CASE(OpFOrdLessThan)
466 CASE(OpFUnordLessThan)
467 CASE(OpUGreaterThan)
468 CASE(OpSGreaterThan)
469 CASE(OpFOrdGreaterThan)
470 CASE(OpFUnordGreaterThan)
471 CASE(OpULessThanEqual)
472 CASE(OpSLessThanEqual)
473 CASE(OpFOrdLessThanEqual)
474 CASE(OpFUnordLessThanEqual)
475 CASE(OpUGreaterThanEqual)
476 CASE(OpSGreaterThanEqual)
477 CASE(OpFOrdGreaterThanEqual)
478 CASE(OpFUnordGreaterThanEqual)
479 CASE(OpDPdx)
480 CASE(OpDPdy)
481 CASE(OpFwidth)
482 CASE(OpDPdxFine)
483 CASE(OpDPdyFine)
484 CASE(OpFwidthFine)
485 CASE(OpDPdxCoarse)
486 CASE(OpDPdyCoarse)
487 CASE(OpFwidthCoarse)
488 CASE(OpEmitVertex)
489 CASE(OpEndPrimitive)
490 CASE(OpEmitStreamVertex)
491 CASE(OpEndStreamPrimitive)
492 CASE(OpControlBarrier)
493 CASE(OpMemoryBarrier)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100494 CASE(OpAtomicLoad)
495 CASE(OpAtomicStore)
496 CASE(OpAtomicExchange)
497 CASE(OpAtomicCompareExchange)
498 CASE(OpAtomicCompareExchangeWeak)
499 CASE(OpAtomicIIncrement)
500 CASE(OpAtomicIDecrement)
501 CASE(OpAtomicIAdd)
502 CASE(OpAtomicISub)
503 CASE(OpAtomicUMin)
504 CASE(OpAtomicUMax)
505 CASE(OpAtomicAnd)
506 CASE(OpAtomicOr)
507 CASE(OpAtomicXor)
508 CASE(OpLoopMerge)
509 CASE(OpSelectionMerge)
510 CASE(OpLabel)
511 CASE(OpBranch)
512 CASE(OpBranchConditional)
513 CASE(OpSwitch)
514 CASE(OpKill)
515 CASE(OpReturn)
516 CASE(OpReturnValue)
517 CASE(OpUnreachable)
518 CASE(OpLifetimeStart)
519 CASE(OpLifetimeStop)
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100520 CASE(OpAsyncGroupCopy)
521 CASE(OpWaitGroupEvents)
522 CASE(OpGroupAll)
523 CASE(OpGroupAny)
524 CASE(OpGroupBroadcast)
525 CASE(OpGroupIAdd)
526 CASE(OpGroupFAdd)
527 CASE(OpGroupFMin)
528 CASE(OpGroupUMin)
529 CASE(OpGroupSMin)
530 CASE(OpGroupFMax)
531 CASE(OpGroupUMax)
532 CASE(OpGroupSMax)
533 CASE(OpGenericCastToPtrExplicit)
534 CASE(OpGenericPtrMemSemantics)
535 CASE(OpReadPipe)
536 CASE(OpWritePipe)
537 CASE(OpReservedReadPipe)
538 CASE(OpReservedWritePipe)
539 CASE(OpReserveReadPipePackets)
540 CASE(OpReserveWritePipePackets)
541 CASE(OpCommitReadPipe)
542 CASE(OpCommitWritePipe)
543 CASE(OpIsValidReserveId)
544 CASE(OpGetNumPipePackets)
545 CASE(OpGetMaxPipePackets)
546 CASE(OpGroupReserveReadPipePackets)
547 CASE(OpGroupReserveWritePipePackets)
548 CASE(OpGroupCommitReadPipe)
549 CASE(OpGroupCommitWritePipe)
550 CASE(OpEnqueueMarker)
551 CASE(OpEnqueueKernel)
552 CASE(OpGetKernelNDrangeSubGroupCount)
553 CASE(OpGetKernelNDrangeMaxSubGroupSize)
554 CASE(OpGetKernelWorkGroupSize)
555 CASE(OpGetKernelPreferredWorkGroupSizeMultiple)
556 CASE(OpRetainEvent)
557 CASE(OpReleaseEvent)
558 CASE(OpCreateUserEvent)
559 CASE(OpIsValidEvent)
560 CASE(OpSetUserEventStatus)
561 CASE(OpCaptureEventProfilingInfo)
562 CASE(OpGetDefaultQueue)
563 CASE(OpBuildNDRange)
564 default:
565 assert(0 && "Unreachable!");
566 }
567#undef CASE
568 return "unknown";
569}
570
571int32_t spvOpcodeIsType(const Op opcode) {
572 switch (opcode) {
573 case OpTypeVoid:
574 case OpTypeBool:
575 case OpTypeInt:
576 case OpTypeFloat:
577 case OpTypeVector:
578 case OpTypeMatrix:
579 case OpTypeSampler:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100580 case OpTypeArray:
581 case OpTypeRuntimeArray:
582 case OpTypeStruct:
583 case OpTypeOpaque:
584 case OpTypePointer:
585 case OpTypeFunction:
586 case OpTypeEvent:
587 case OpTypeDeviceEvent:
588 case OpTypeReserveId:
589 case OpTypeQueue:
590 case OpTypePipe:
591 return true;
592 default:
593 return false;
594 }
595}
596
597int32_t spvOpcodeIsScalarType(const Op opcode) {
598 switch (opcode) {
599 case OpTypeInt:
600 case OpTypeFloat:
601 return true;
602 default:
603 return false;
604 }
605}
606
607int32_t spvOpcodeIsConstant(const Op opcode) {
608 switch (opcode) {
609 case OpConstantTrue:
610 case OpConstantFalse:
611 case OpConstant:
612 case OpConstantComposite:
613 case OpConstantSampler:
614 // case OpConstantNull:
615 case OpConstantNull:
616 case OpSpecConstantTrue:
617 case OpSpecConstantFalse:
618 case OpSpecConstant:
619 case OpSpecConstantComposite:
620 // case OpSpecConstantOp:
621 return true;
622 default:
623 return false;
624 }
625}
626
627int32_t spvOpcodeIsComposite(const Op opcode) {
628 switch (opcode) {
629 case OpTypeVector:
630 case OpTypeMatrix:
631 case OpTypeArray:
632 case OpTypeStruct:
633 return true;
634 default:
635 return false;
636 }
637}
638
639int32_t spvOpcodeAreTypesEqual(const spv_instruction_t *pTypeInst0,
640 const spv_instruction_t *pTypeInst1) {
Lei Zhang40056702015-09-11 14:31:27 -0400641 if (pTypeInst0->opcode != pTypeInst1->opcode) return false;
642 if (pTypeInst0->words[1] != pTypeInst1->words[1]) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100643 return true;
644}
645
646int32_t spvOpcodeIsPointer(const Op opcode) {
647 switch (opcode) {
648 case OpVariable:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100649 case OpAccessChain:
650 case OpInBoundsAccessChain:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100651 case OpFunctionParameter:
652 return true;
653 default:
654 return false;
655 }
656}
657
658int32_t spvOpcodeIsObject(const Op opcode) {
659 switch (opcode) {
660 case OpConstantTrue:
661 case OpConstantFalse:
662 case OpConstant:
663 case OpConstantComposite:
664 // TODO: case OpConstantSampler:
665 case OpConstantNull:
666 case OpSpecConstantTrue:
667 case OpSpecConstantFalse:
668 case OpSpecConstant:
669 case OpSpecConstantComposite:
670 // TODO: case OpSpecConstantOp:
671 case OpVariable:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100672 case OpAccessChain:
673 case OpInBoundsAccessChain:
674 case OpConvertFToU:
675 case OpConvertFToS:
676 case OpConvertSToF:
677 case OpConvertUToF:
678 case OpUConvert:
679 case OpSConvert:
680 case OpFConvert:
681 case OpConvertPtrToU:
682 // TODO: case OpConvertUToPtr:
683 case OpPtrCastToGeneric:
684 // TODO: case OpGenericCastToPtr:
685 case OpBitcast:
686 // TODO: case OpGenericCastToPtrExplicit:
687 case OpSatConvertSToU:
688 case OpSatConvertUToS:
689 case OpVectorExtractDynamic:
690 case OpCompositeConstruct:
691 case OpCompositeExtract:
692 case OpCopyObject:
693 case OpTranspose:
694 case OpSNegate:
695 case OpFNegate:
696 case OpNot:
697 case OpIAdd:
698 case OpFAdd:
699 case OpISub:
700 case OpFSub:
701 case OpIMul:
702 case OpFMul:
703 case OpUDiv:
704 case OpSDiv:
705 case OpFDiv:
706 case OpUMod:
707 case OpSRem:
708 case OpSMod:
709 case OpVectorTimesScalar:
710 case OpMatrixTimesScalar:
711 case OpVectorTimesMatrix:
712 case OpMatrixTimesVector:
713 case OpMatrixTimesMatrix:
714 case OpOuterProduct:
715 case OpDot:
716 case OpShiftRightLogical:
717 case OpShiftRightArithmetic:
718 case OpShiftLeftLogical:
719 case OpBitwiseOr:
720 case OpBitwiseXor:
721 case OpBitwiseAnd:
722 case OpAny:
723 case OpAll:
724 case OpIsNan:
725 case OpIsInf:
726 case OpIsFinite:
727 case OpIsNormal:
728 case OpSignBitSet:
729 case OpLessOrGreater:
730 case OpOrdered:
731 case OpUnordered:
732 case OpLogicalOr:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100733 case OpLogicalAnd:
734 case OpSelect:
735 case OpIEqual:
736 case OpFOrdEqual:
737 case OpFUnordEqual:
738 case OpINotEqual:
739 case OpFOrdNotEqual:
740 case OpFUnordNotEqual:
741 case OpULessThan:
742 case OpSLessThan:
743 case OpFOrdLessThan:
744 case OpFUnordLessThan:
745 case OpUGreaterThan:
746 case OpSGreaterThan:
747 case OpFOrdGreaterThan:
748 case OpFUnordGreaterThan:
749 case OpULessThanEqual:
750 case OpSLessThanEqual:
751 case OpFOrdLessThanEqual:
752 case OpFUnordLessThanEqual:
753 case OpUGreaterThanEqual:
754 case OpSGreaterThanEqual:
755 case OpFOrdGreaterThanEqual:
756 case OpFUnordGreaterThanEqual:
757 case OpDPdx:
758 case OpDPdy:
759 case OpFwidth:
760 case OpDPdxFine:
761 case OpDPdyFine:
762 case OpFwidthFine:
763 case OpDPdxCoarse:
764 case OpDPdyCoarse:
765 case OpFwidthCoarse:
766 case OpReturnValue:
767 return true;
768 default:
769 return false;
770 }
771}
772
773int32_t spvOpcodeIsBasicTypeNullable(Op opcode) {
774 switch (opcode) {
775 case OpTypeBool:
776 case OpTypeInt:
777 case OpTypeFloat:
778 case OpTypePointer:
779 case OpTypeEvent:
780 case OpTypeDeviceEvent:
781 case OpTypeReserveId:
782 case OpTypeQueue:
783 return true;
784 default:
785 return false;
786 }
787}
788
789int32_t spvInstructionIsInBasicBlock(const spv_instruction_t *pFirstInst,
790 const spv_instruction_t *pInst) {
791 while (pFirstInst != pInst) {
Lei Zhang40056702015-09-11 14:31:27 -0400792 if (OpFunction == pInst->opcode) break;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100793 pInst--;
794 }
Lei Zhang40056702015-09-11 14:31:27 -0400795 if (OpFunction != pInst->opcode) return false;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100796 return true;
797}
798
799int32_t spvOpcodeIsValue(Op opcode) {
Lei Zhang40056702015-09-11 14:31:27 -0400800 if (spvOpcodeIsPointer(opcode)) return true;
801 if (spvOpcodeIsConstant(opcode)) return true;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100802 switch (opcode) {
803 case OpLoad:
804 // TODO: Other Opcode's resulting in a value
805 return true;
806 default:
807 return false;
808 }
809}
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400810
811int32_t spvOpcodeGeneratesType(Op op) {
812 switch(op) {
813 case OpTypeVoid:
814 case OpTypeBool:
815 case OpTypeInt:
816 case OpTypeFloat:
817 case OpTypeVector:
818 case OpTypeMatrix:
819 case OpTypeImage:
820 case OpTypeSampler:
821 case OpTypeSampledImage:
822 case OpTypeArray:
823 case OpTypeRuntimeArray:
824 case OpTypeStruct:
825 case OpTypeOpaque:
826 case OpTypePointer:
827 case OpTypeFunction:
828 case OpTypeEvent:
829 case OpTypeDeviceEvent:
830 case OpTypeReserveId:
831 case OpTypeQueue:
832 case OpTypePipe:
833 case OpTypeForwardPointer:
834 return true;
835 default:;
836 }
837 return 0;
838}