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