blob: 80fe3b3a9f94a5b8b6af13d9e1e138f33db32a7c [file] [log] [blame]
Daniel Koch5a97e3a2020-03-17 15:30:19 -04001// Copyright (c) 2015-2020 The Khronos Group Inc.
2// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights
3// reserved.
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +01004//
David Neto9fc86582016-09-01 15:33:59 -04005// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +01008//
David Neto9fc86582016-09-01 15:33:59 -04009// http://www.apache.org/licenses/LICENSE-2.0
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010010//
David Neto9fc86582016-09-01 15:33:59 -040011// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010016
dan sinclaireda2cfb2018-08-03 15:06:09 -040017#include "source/opcode.h"
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010018
19#include <assert.h>
20#include <string.h>
21
David Neto5a0b5ca2016-12-09 14:01:43 -050022#include <algorithm>
Lei Zhang972788b2015-11-12 13:48:30 -050023#include <cstdlib>
24
dan sinclaireda2cfb2018-08-03 15:06:09 -040025#include "source/instruction.h"
26#include "source/macro.h"
27#include "source/spirv_constant.h"
28#include "source/spirv_endian.h"
29#include "source/spirv_target_env.h"
David Neto5a703352016-02-17 14:44:00 -050030#include "spirv-tools/libspirv.h"
Lei Zhang923f6c12015-11-11 12:45:23 -050031
David Neto78c3b432015-08-27 13:03:52 -040032namespace {
Lei Zhang16981f82017-09-21 17:24:57 -040033struct OpcodeDescPtrLen {
34 const spv_opcode_desc_t* ptr;
35 uint32_t len;
36};
David Neto78c3b432015-08-27 13:03:52 -040037
dan sinclaireda2cfb2018-08-03 15:06:09 -040038#include "core.insts-unified1.inc"
Lei Zhang16981f82017-09-21 17:24:57 -040039
Lei Zhang1ef6b192018-03-14 13:06:18 -040040static const spv_opcode_table_t kOpcodeTable = {ARRAY_SIZE(kOpcodeTableEntries),
41 kOpcodeTableEntries};
David Neto78c3b432015-08-27 13:03:52 -040042
David Neto5a0b5ca2016-12-09 14:01:43 -050043// Represents a vendor tool entry in the SPIR-V XML Regsitry.
44struct VendorTool {
45 uint32_t value;
46 const char* vendor;
Lei Zhang16981f82017-09-21 17:24:57 -040047 const char* tool; // Might be empty string.
48 const char* vendor_tool; // Combiantion of vendor and tool.
David Neto5a0b5ca2016-12-09 14:01:43 -050049};
50
51const VendorTool vendor_tools[] = {
52#include "generators.inc"
53};
54
Lei Zhanga94701d2015-09-14 10:05:37 -040055} // anonymous namespace
David Neto78c3b432015-08-27 13:03:52 -040056
David Neto5a0b5ca2016-12-09 14:01:43 -050057// TODO(dneto): Move this to another file. It doesn't belong with opcode
58// processing.
Lei Zhang1a0334e2015-11-02 09:41:20 -050059const char* spvGeneratorStr(uint32_t generator) {
David Neto5a0b5ca2016-12-09 14:01:43 -050060 auto where = std::find_if(
61 std::begin(vendor_tools), std::end(vendor_tools),
62 [generator](const VendorTool& vt) { return generator == vt.value; });
63 if (where != std::end(vendor_tools)) return where->vendor_tool;
64 return "Unknown";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010065}
66
Lei Zhangb36e7042015-10-28 13:40:52 -040067uint32_t spvOpcodeMake(uint16_t wordCount, SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010068 return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
69}
70
Lei Zhang6fa3f8a2016-03-31 17:26:31 -040071void spvOpcodeSplit(const uint32_t word, uint16_t* pWordCount,
72 uint16_t* pOpcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010073 if (pWordCount) {
74 *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
75 }
76 if (pOpcode) {
Lei Zhang6fa3f8a2016-03-31 17:26:31 -040077 *pOpcode = 0x0000ffff & word;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010078 }
79}
80
Lei Zhang1ef6b192018-03-14 13:06:18 -040081spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable, spv_target_env) {
Lei Zhang40056702015-09-11 14:31:27 -040082 if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010083
Lei Zhang16981f82017-09-21 17:24:57 -040084 // Descriptions of each opcode. Each entry describes the format of the
85 // instruction that follows a particular opcode.
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010086
Lei Zhang1ef6b192018-03-14 13:06:18 -040087 *pInstTable = &kOpcodeTable;
88 return SPV_SUCCESS;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010089}
90
Lei Zhang1ef6b192018-03-14 13:06:18 -040091spv_result_t spvOpcodeTableNameLookup(spv_target_env env,
92 const spv_opcode_table table,
Lei Zhang1a0334e2015-11-02 09:41:20 -050093 const char* name,
94 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -040095 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
96 if (!table) return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010097
98 // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
99 // preferable but the table requires sorting on the Opcode name, but it's
Lei Zhang1ef6b192018-03-14 13:06:18 -0400100 // static const initialized and matches the order of the spec.
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100101 const size_t nameLength = strlen(name);
alan-baker45fb6962019-05-10 11:02:01 -0400102 const auto version = spvVersionForTargetEnv(env);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100103 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
Lei Zhang1ef6b192018-03-14 13:06:18 -0400104 const spv_opcode_desc_t& entry = table->entries[opcodeIndex];
105 // We considers the current opcode as available as long as
106 // 1. The target environment satisfies the minimal requirement of the
107 // opcode; or
108 // 2. There is at least one extension enabling this opcode.
109 //
110 // Note that the second rule assumes the extension enabling this instruction
111 // is indeed requested in the SPIR-V code; checking that should be
112 // validator's work.
alan-baker45fb6962019-05-10 11:02:01 -0400113 if (((version >= entry.minVersion && version <= entry.lastVersion) ||
David Neto8d65c892018-06-19 09:54:33 -0400114 entry.numExtensions > 0u || entry.numCapabilities > 0u) &&
Lei Zhang1ef6b192018-03-14 13:06:18 -0400115 nameLength == strlen(entry.name) &&
116 !strncmp(name, entry.name, nameLength)) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100117 // NOTE: Found out Opcode!
Lei Zhang1ef6b192018-03-14 13:06:18 -0400118 *pEntry = &entry;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100119 return SPV_SUCCESS;
120 }
121 }
122
123 return SPV_ERROR_INVALID_LOOKUP;
124}
125
Lei Zhang1ef6b192018-03-14 13:06:18 -0400126spv_result_t spvOpcodeTableValueLookup(spv_target_env env,
127 const spv_opcode_table table,
Lei Zhangb36e7042015-10-28 13:40:52 -0400128 const SpvOp opcode,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500129 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400130 if (!table) return SPV_ERROR_INVALID_TABLE;
131 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100132
Jesus Carabanof063f912017-10-27 15:28:50 +0300133 const auto beg = table->entries;
134 const auto end = table->entries + table->count;
Lei Zhang1ef6b192018-03-14 13:06:18 -0400135
alan-baker45fb6962019-05-10 11:02:01 -0400136 spv_opcode_desc_t needle = {"", opcode, 0, nullptr, 0, {},
137 false, false, 0, nullptr, ~0u, ~0u};
Lei Zhang1ef6b192018-03-14 13:06:18 -0400138
Jesus Carabanof063f912017-10-27 15:28:50 +0300139 auto comp = [](const spv_opcode_desc_t& lhs, const spv_opcode_desc_t& rhs) {
140 return lhs.opcode < rhs.opcode;
141 };
Lei Zhang1ef6b192018-03-14 13:06:18 -0400142
143 // We need to loop here because there can exist multiple symbols for the same
144 // opcode value, and they can be introduced in different target environments,
145 // which means they can have different minimal version requirements.
146 // Assumes the underlying table is already sorted ascendingly according to
147 // opcode value.
alan-baker45fb6962019-05-10 11:02:01 -0400148 const auto version = spvVersionForTargetEnv(env);
Lei Zhang1ef6b192018-03-14 13:06:18 -0400149 for (auto it = std::lower_bound(beg, end, needle, comp);
150 it != end && it->opcode == opcode; ++it) {
151 // We considers the current opcode as available as long as
152 // 1. The target environment satisfies the minimal requirement of the
153 // opcode; or
154 // 2. There is at least one extension enabling this opcode.
155 //
156 // Note that the second rule assumes the extension enabling this instruction
157 // is indeed requested in the SPIR-V code; checking that should be
158 // validator's work.
alan-baker45fb6962019-05-10 11:02:01 -0400159 if ((version >= it->minVersion && version <= it->lastVersion) ||
David Neto8d65c892018-06-19 09:54:33 -0400160 it->numExtensions > 0u || it->numCapabilities > 0u) {
Lei Zhang1ef6b192018-03-14 13:06:18 -0400161 *pEntry = it;
162 return SPV_SUCCESS;
163 }
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100164 }
165
166 return SPV_ERROR_INVALID_LOOKUP;
167}
168
Lei Zhang1a0334e2015-11-02 09:41:20 -0500169void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100170 const uint16_t wordCount, const spv_endianness_t endian,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500171 spv_instruction_t* pInst) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100172 pInst->opcode = opcode;
David Netob5dc8fc2015-10-06 16:22:00 -0400173 pInst->words.resize(wordCount);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100174 for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
175 pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
176 if (!wordIndex) {
177 uint16_t thisWordCount;
Lei Zhang6fa3f8a2016-03-31 17:26:31 -0400178 uint16_t thisOpcode;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100179 spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
Lei Zhang6fa3f8a2016-03-31 17:26:31 -0400180 assert(opcode == static_cast<SpvOp>(thisOpcode) &&
181 wordCount == thisWordCount && "Endianness failed!");
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100182 }
183 }
184}
185
Steven Perron4a804972020-02-20 14:07:57 -0500186const char* spvOpcodeString(const uint32_t opcode) {
Lei Zhang1ef6b192018-03-14 13:06:18 -0400187 const auto beg = kOpcodeTableEntries;
188 const auto end = kOpcodeTableEntries + ARRAY_SIZE(kOpcodeTableEntries);
Ricardo Garciadea10402020-02-21 21:06:46 +0100189 spv_opcode_desc_t needle = {"", static_cast<SpvOp>(opcode),
Steven Perron4a804972020-02-20 14:07:57 -0500190 0, nullptr,
191 0, {},
192 false, false,
193 0, nullptr,
194 ~0u, ~0u};
Jesus Carabanof063f912017-10-27 15:28:50 +0300195 auto comp = [](const spv_opcode_desc_t& lhs, const spv_opcode_desc_t& rhs) {
196 return lhs.opcode < rhs.opcode;
197 };
Lei Zhang1ef6b192018-03-14 13:06:18 -0400198 auto it = std::lower_bound(beg, end, needle, comp);
Diego Novillod2938e42017-11-08 12:40:02 -0500199 if (it != end && it->opcode == opcode) {
Jesus Carabanof063f912017-10-27 15:28:50 +0300200 return it->name;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100201 }
Lei Zhang16981f82017-09-21 17:24:57 -0400202
Lei Zhang4f293b72016-03-21 16:36:14 -0400203 assert(0 && "Unreachable!");
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100204 return "unknown";
205}
206
Lei Zhangb36e7042015-10-28 13:40:52 -0400207int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100208 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400209 case SpvOpTypeInt:
210 case SpvOpTypeFloat:
Dejan Mircevski276a7242016-01-21 15:55:43 -0500211 case SpvOpTypeBool:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100212 return true;
213 default:
214 return false;
215 }
216}
217
Alan Baker0a2ee652018-03-23 14:18:54 -0400218int32_t spvOpcodeIsSpecConstant(const SpvOp opcode) {
219 switch (opcode) {
220 case SpvOpSpecConstantTrue:
221 case SpvOpSpecConstantFalse:
222 case SpvOpSpecConstant:
223 case SpvOpSpecConstantComposite:
224 case SpvOpSpecConstantOp:
225 return true;
226 default:
227 return false;
228 }
229}
230
Lei Zhangb36e7042015-10-28 13:40:52 -0400231int32_t spvOpcodeIsConstant(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100232 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400233 case SpvOpConstantTrue:
234 case SpvOpConstantFalse:
235 case SpvOpConstant:
236 case SpvOpConstantComposite:
237 case SpvOpConstantSampler:
Lei Zhangb36e7042015-10-28 13:40:52 -0400238 case SpvOpConstantNull:
239 case SpvOpSpecConstantTrue:
240 case SpvOpSpecConstantFalse:
241 case SpvOpSpecConstant:
242 case SpvOpSpecConstantComposite:
Dejan Mircevski3fb26762016-04-04 15:55:05 -0400243 case SpvOpSpecConstantOp:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100244 return true;
245 default:
246 return false;
247 }
248}
249
David Neto1f3fb502016-09-14 11:57:20 -0400250bool spvOpcodeIsConstantOrUndef(const SpvOp opcode) {
251 return opcode == SpvOpUndef || spvOpcodeIsConstant(opcode);
252}
253
Aliya Pazylbekovaedb52642017-02-24 20:43:28 -0500254bool spvOpcodeIsScalarSpecConstant(const SpvOp opcode) {
255 switch (opcode) {
256 case SpvOpSpecConstantTrue:
257 case SpvOpSpecConstantFalse:
258 case SpvOpSpecConstant:
259 return true;
260 default:
261 return false;
262 }
263}
264
Lei Zhangb36e7042015-10-28 13:40:52 -0400265int32_t spvOpcodeIsComposite(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100266 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400267 case SpvOpTypeVector:
268 case SpvOpTypeMatrix:
269 case SpvOpTypeArray:
270 case SpvOpTypeStruct:
Jeff Bolz002ef362019-02-25 16:43:11 -0600271 case SpvOpTypeCooperativeMatrixNV:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100272 return true;
273 default:
274 return false;
275 }
276}
277
Ehsan Nasiri23af06c2017-02-01 15:37:39 -0500278bool spvOpcodeReturnsLogicalVariablePointer(const SpvOp opcode) {
279 switch (opcode) {
280 case SpvOpVariable:
281 case SpvOpAccessChain:
282 case SpvOpInBoundsAccessChain:
283 case SpvOpFunctionParameter:
284 case SpvOpImageTexelPointer:
285 case SpvOpCopyObject:
286 case SpvOpSelect:
287 case SpvOpPhi:
288 case SpvOpFunctionCall:
289 case SpvOpPtrAccessChain:
290 case SpvOpLoad:
291 case SpvOpConstantNull:
292 return true;
293 default:
294 return false;
295 }
296}
297
Florian Ziesche66fcb452016-03-02 22:17:54 +0100298int32_t spvOpcodeReturnsLogicalPointer(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100299 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400300 case SpvOpVariable:
301 case SpvOpAccessChain:
302 case SpvOpInBoundsAccessChain:
303 case SpvOpFunctionParameter:
Florian Ziesche66fcb452016-03-02 22:17:54 +0100304 case SpvOpImageTexelPointer:
305 case SpvOpCopyObject:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100306 return true;
307 default:
308 return false;
309 }
310}
311
Lei Zhangb36e7042015-10-28 13:40:52 -0400312int32_t spvOpcodeGeneratesType(SpvOp op) {
Lei Zhang1a0334e2015-11-02 09:41:20 -0500313 switch (op) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400314 case SpvOpTypeVoid:
315 case SpvOpTypeBool:
316 case SpvOpTypeInt:
317 case SpvOpTypeFloat:
318 case SpvOpTypeVector:
319 case SpvOpTypeMatrix:
320 case SpvOpTypeImage:
321 case SpvOpTypeSampler:
322 case SpvOpTypeSampledImage:
323 case SpvOpTypeArray:
324 case SpvOpTypeRuntimeArray:
325 case SpvOpTypeStruct:
326 case SpvOpTypeOpaque:
327 case SpvOpTypePointer:
328 case SpvOpTypeFunction:
329 case SpvOpTypeEvent:
330 case SpvOpTypeDeviceEvent:
331 case SpvOpTypeReserveId:
332 case SpvOpTypeQueue:
333 case SpvOpTypePipe:
Andrey Tuganov4ef3b3e2017-02-28 11:53:47 -0500334 case SpvOpTypePipeStorage:
335 case SpvOpTypeNamedBarrier:
alelenv1c1e7492018-10-25 11:07:46 -0700336 case SpvOpTypeAccelerationStructureNV:
Jeff Bolz002ef362019-02-25 16:43:11 -0600337 case SpvOpTypeCooperativeMatrixNV:
Daniel Koch5a97e3a2020-03-17 15:30:19 -0400338 // case SpvOpTypeAccelerationStructureKHR: covered by
339 // SpvOpTypeAccelerationStructureNV
340 case SpvOpTypeRayQueryProvisionalKHR:
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400341 return true;
David Netoaef608c2015-11-02 14:59:02 -0500342 default:
343 // In particular, OpTypeForwardPointer does not generate a type,
344 // but declares a storage class for a pointer type generated
345 // by a different instruction.
346 break;
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400347 }
348 return 0;
349}
Steven Perroneb4653a2017-11-13 15:31:43 -0500350
351bool spvOpcodeIsDecoration(const SpvOp opcode) {
Steven Perron28c41552017-11-10 20:26:55 -0500352 switch (opcode) {
Steven Perroneb4653a2017-11-13 15:31:43 -0500353 case SpvOpDecorate:
354 case SpvOpDecorateId:
355 case SpvOpMemberDecorate:
356 case SpvOpGroupDecorate:
357 case SpvOpGroupMemberDecorate:
David Neto5f69f752018-03-05 13:34:13 -0500358 case SpvOpDecorateStringGOOGLE:
359 case SpvOpMemberDecorateStringGOOGLE:
Steven Perroneb4653a2017-11-13 15:31:43 -0500360 return true;
361 default:
362 break;
363 }
364 return false;
365}
Steven Perron28c41552017-11-10 20:26:55 -0500366
367bool spvOpcodeIsLoad(const SpvOp opcode) {
368 switch (opcode) {
369 case SpvOpLoad:
370 case SpvOpImageSampleExplicitLod:
371 case SpvOpImageSampleImplicitLod:
372 case SpvOpImageSampleDrefImplicitLod:
373 case SpvOpImageSampleDrefExplicitLod:
374 case SpvOpImageSampleProjImplicitLod:
375 case SpvOpImageSampleProjExplicitLod:
376 case SpvOpImageSampleProjDrefImplicitLod:
377 case SpvOpImageSampleProjDrefExplicitLod:
378 case SpvOpImageFetch:
379 case SpvOpImageGather:
380 case SpvOpImageDrefGather:
381 case SpvOpImageRead:
382 case SpvOpImageSparseSampleImplicitLod:
383 case SpvOpImageSparseSampleExplicitLod:
384 case SpvOpImageSparseSampleDrefExplicitLod:
385 case SpvOpImageSparseSampleDrefImplicitLod:
386 case SpvOpImageSparseFetch:
387 case SpvOpImageSparseGather:
388 case SpvOpImageSparseDrefGather:
389 case SpvOpImageSparseRead:
390 return true;
391 default:
392 return false;
393 }
394}
395
Diego Novillo74327842017-11-17 08:59:25 -0500396bool spvOpcodeIsBranch(SpvOp opcode) {
397 switch (opcode) {
398 case SpvOpBranch:
399 case SpvOpBranchConditional:
400 case SpvOpSwitch:
401 return true;
402 default:
403 return false;
404 }
405}
406
greg-lunarge5455642018-10-12 06:46:35 -0600407bool spvOpcodeIsAtomicWithLoad(const SpvOp opcode) {
Steven Perron28c41552017-11-10 20:26:55 -0500408 switch (opcode) {
409 case SpvOpAtomicLoad:
Steven Perron28c41552017-11-10 20:26:55 -0500410 case SpvOpAtomicExchange:
411 case SpvOpAtomicCompareExchange:
412 case SpvOpAtomicCompareExchangeWeak:
413 case SpvOpAtomicIIncrement:
414 case SpvOpAtomicIDecrement:
415 case SpvOpAtomicIAdd:
416 case SpvOpAtomicISub:
417 case SpvOpAtomicSMin:
418 case SpvOpAtomicUMin:
419 case SpvOpAtomicSMax:
420 case SpvOpAtomicUMax:
421 case SpvOpAtomicAnd:
422 case SpvOpAtomicOr:
423 case SpvOpAtomicXor:
424 case SpvOpAtomicFlagTestAndSet:
Steven Perron28c41552017-11-10 20:26:55 -0500425 return true;
426 default:
427 return false;
428 }
429}
Diego Novillo74327842017-11-17 08:59:25 -0500430
greg-lunarge5455642018-10-12 06:46:35 -0600431bool spvOpcodeIsAtomicOp(const SpvOp opcode) {
432 return (spvOpcodeIsAtomicWithLoad(opcode) || opcode == SpvOpAtomicStore ||
433 opcode == SpvOpAtomicFlagClear);
434}
435
Diego Novillo74327842017-11-17 08:59:25 -0500436bool spvOpcodeIsReturn(SpvOp opcode) {
437 switch (opcode) {
438 case SpvOpReturn:
439 case SpvOpReturnValue:
440 return true;
441 default:
442 return false;
443 }
444}
445
Diego Novillo5f100782018-01-03 15:25:03 -0500446bool spvOpcodeIsReturnOrAbort(SpvOp opcode) {
447 return spvOpcodeIsReturn(opcode) || opcode == SpvOpKill ||
448 opcode == SpvOpUnreachable;
449}
450
Diego Novillo74327842017-11-17 08:59:25 -0500451bool spvOpcodeIsBlockTerminator(SpvOp opcode) {
Diego Novillo5f100782018-01-03 15:25:03 -0500452 return spvOpcodeIsBranch(opcode) || spvOpcodeIsReturnOrAbort(opcode);
Diego Novillo74327842017-11-17 08:59:25 -0500453}
Steven Perron79a00642017-12-11 13:10:24 -0500454
455bool spvOpcodeIsBaseOpaqueType(SpvOp opcode) {
456 switch (opcode) {
457 case SpvOpTypeImage:
458 case SpvOpTypeSampler:
459 case SpvOpTypeSampledImage:
460 case SpvOpTypeOpaque:
461 case SpvOpTypeEvent:
462 case SpvOpTypeDeviceEvent:
463 case SpvOpTypeReserveId:
464 case SpvOpTypeQueue:
465 case SpvOpTypePipe:
466 case SpvOpTypeForwardPointer:
467 case SpvOpTypePipeStorage:
468 case SpvOpTypeNamedBarrier:
469 return true;
470 default:
471 return false;
472 }
473}
Alan Baker09c206b2018-04-17 10:18:59 -0400474
475bool spvOpcodeIsNonUniformGroupOperation(SpvOp opcode) {
476 switch (opcode) {
477 case SpvOpGroupNonUniformElect:
478 case SpvOpGroupNonUniformAll:
479 case SpvOpGroupNonUniformAny:
480 case SpvOpGroupNonUniformAllEqual:
481 case SpvOpGroupNonUniformBroadcast:
482 case SpvOpGroupNonUniformBroadcastFirst:
483 case SpvOpGroupNonUniformBallot:
484 case SpvOpGroupNonUniformInverseBallot:
485 case SpvOpGroupNonUniformBallotBitExtract:
486 case SpvOpGroupNonUniformBallotBitCount:
487 case SpvOpGroupNonUniformBallotFindLSB:
488 case SpvOpGroupNonUniformBallotFindMSB:
489 case SpvOpGroupNonUniformShuffle:
490 case SpvOpGroupNonUniformShuffleXor:
491 case SpvOpGroupNonUniformShuffleUp:
492 case SpvOpGroupNonUniformShuffleDown:
493 case SpvOpGroupNonUniformIAdd:
494 case SpvOpGroupNonUniformFAdd:
495 case SpvOpGroupNonUniformIMul:
496 case SpvOpGroupNonUniformFMul:
497 case SpvOpGroupNonUniformSMin:
498 case SpvOpGroupNonUniformUMin:
499 case SpvOpGroupNonUniformFMin:
500 case SpvOpGroupNonUniformSMax:
501 case SpvOpGroupNonUniformUMax:
502 case SpvOpGroupNonUniformFMax:
503 case SpvOpGroupNonUniformBitwiseAnd:
504 case SpvOpGroupNonUniformBitwiseOr:
505 case SpvOpGroupNonUniformBitwiseXor:
506 case SpvOpGroupNonUniformLogicalAnd:
507 case SpvOpGroupNonUniformLogicalOr:
508 case SpvOpGroupNonUniformLogicalXor:
509 case SpvOpGroupNonUniformQuadBroadcast:
510 case SpvOpGroupNonUniformQuadSwap:
511 return true;
512 default:
513 return false;
514 }
515}
Steven Perron2c0ce872018-04-23 11:13:07 -0400516
517bool spvOpcodeIsScalarizable(SpvOp opcode) {
518 switch (opcode) {
519 case SpvOpPhi:
520 case SpvOpCopyObject:
521 case SpvOpConvertFToU:
522 case SpvOpConvertFToS:
523 case SpvOpConvertSToF:
524 case SpvOpConvertUToF:
525 case SpvOpUConvert:
526 case SpvOpSConvert:
527 case SpvOpFConvert:
528 case SpvOpQuantizeToF16:
529 case SpvOpVectorInsertDynamic:
530 case SpvOpSNegate:
531 case SpvOpFNegate:
532 case SpvOpIAdd:
533 case SpvOpFAdd:
534 case SpvOpISub:
535 case SpvOpFSub:
536 case SpvOpIMul:
537 case SpvOpFMul:
538 case SpvOpUDiv:
539 case SpvOpSDiv:
540 case SpvOpFDiv:
541 case SpvOpUMod:
542 case SpvOpSRem:
543 case SpvOpSMod:
544 case SpvOpFRem:
545 case SpvOpFMod:
546 case SpvOpVectorTimesScalar:
547 case SpvOpIAddCarry:
548 case SpvOpISubBorrow:
549 case SpvOpUMulExtended:
550 case SpvOpSMulExtended:
551 case SpvOpShiftRightLogical:
552 case SpvOpShiftRightArithmetic:
553 case SpvOpShiftLeftLogical:
554 case SpvOpBitwiseOr:
555 case SpvOpBitwiseAnd:
556 case SpvOpNot:
557 case SpvOpBitFieldInsert:
558 case SpvOpBitFieldSExtract:
559 case SpvOpBitFieldUExtract:
560 case SpvOpBitReverse:
561 case SpvOpBitCount:
562 case SpvOpIsNan:
563 case SpvOpIsInf:
564 case SpvOpIsFinite:
565 case SpvOpIsNormal:
566 case SpvOpSignBitSet:
567 case SpvOpLessOrGreater:
568 case SpvOpOrdered:
569 case SpvOpUnordered:
570 case SpvOpLogicalEqual:
571 case SpvOpLogicalNotEqual:
572 case SpvOpLogicalOr:
573 case SpvOpLogicalAnd:
574 case SpvOpLogicalNot:
575 case SpvOpSelect:
576 case SpvOpIEqual:
577 case SpvOpINotEqual:
578 case SpvOpUGreaterThan:
579 case SpvOpSGreaterThan:
580 case SpvOpUGreaterThanEqual:
581 case SpvOpSGreaterThanEqual:
582 case SpvOpULessThan:
583 case SpvOpSLessThan:
584 case SpvOpULessThanEqual:
585 case SpvOpSLessThanEqual:
586 case SpvOpFOrdEqual:
587 case SpvOpFUnordEqual:
588 case SpvOpFOrdNotEqual:
589 case SpvOpFUnordNotEqual:
590 case SpvOpFOrdLessThan:
591 case SpvOpFUnordLessThan:
592 case SpvOpFOrdGreaterThan:
593 case SpvOpFUnordGreaterThan:
594 case SpvOpFOrdLessThanEqual:
595 case SpvOpFUnordLessThanEqual:
596 case SpvOpFOrdGreaterThanEqual:
597 case SpvOpFUnordGreaterThanEqual:
598 return true;
599 default:
600 return false;
601 }
602}
Ryan Harrison11c7a9e2018-11-20 16:12:28 -0500603
604bool spvOpcodeIsDebug(SpvOp opcode) {
605 switch (opcode) {
606 case SpvOpName:
607 case SpvOpMemberName:
608 case SpvOpSource:
609 case SpvOpSourceContinued:
610 case SpvOpSourceExtension:
611 case SpvOpString:
612 case SpvOpLine:
613 case SpvOpNoLine:
614 return true;
615 default:
616 return false;
617 }
618}
Ryan Harrisone5455222019-03-14 13:34:33 -0400619
Alastair Donaldson66a682b2020-03-05 08:18:39 +0000620bool spvOpcodeIsCommutativeBinaryOperator(SpvOp opcode) {
621 switch (opcode) {
622 case SpvOpPtrEqual:
623 case SpvOpPtrNotEqual:
624 case SpvOpIAdd:
625 case SpvOpFAdd:
626 case SpvOpIMul:
627 case SpvOpFMul:
628 case SpvOpDot:
629 case SpvOpIAddCarry:
630 case SpvOpUMulExtended:
631 case SpvOpSMulExtended:
632 case SpvOpBitwiseOr:
633 case SpvOpBitwiseXor:
634 case SpvOpBitwiseAnd:
635 case SpvOpOrdered:
636 case SpvOpUnordered:
637 case SpvOpLogicalEqual:
638 case SpvOpLogicalNotEqual:
639 case SpvOpLogicalOr:
640 case SpvOpLogicalAnd:
641 case SpvOpIEqual:
642 case SpvOpINotEqual:
643 case SpvOpFOrdEqual:
644 case SpvOpFUnordEqual:
645 case SpvOpFOrdNotEqual:
646 case SpvOpFUnordNotEqual:
647 return true;
648 default:
649 return false;
650 }
651}
652
Ryan Harrisone5455222019-03-14 13:34:33 -0400653std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode) {
654 switch (opcode) {
655 case SpvOpMemoryBarrier:
656 return {1};
657 case SpvOpAtomicStore:
658 case SpvOpControlBarrier:
659 case SpvOpAtomicFlagClear:
660 case SpvOpMemoryNamedBarrier:
661 return {2};
662 case SpvOpAtomicLoad:
663 case SpvOpAtomicExchange:
664 case SpvOpAtomicIIncrement:
665 case SpvOpAtomicIDecrement:
666 case SpvOpAtomicIAdd:
667 case SpvOpAtomicISub:
668 case SpvOpAtomicSMin:
669 case SpvOpAtomicUMin:
670 case SpvOpAtomicSMax:
671 case SpvOpAtomicUMax:
672 case SpvOpAtomicAnd:
673 case SpvOpAtomicOr:
674 case SpvOpAtomicXor:
675 case SpvOpAtomicFlagTestAndSet:
676 return {4};
677 case SpvOpAtomicCompareExchange:
678 case SpvOpAtomicCompareExchangeWeak:
679 return {4, 5};
680 default:
681 return {};
682 }
683}