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