blob: a837b95121a9463ae4bd3782bfcd0a8f6891d1a5 [file] [log] [blame]
Dejan Mircevskib6fe02f2016-01-07 13:44:22 -05001// Copyright (c) 2015-2016 The Khronos Group Inc.
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +01002//
David Neto9fc86582016-09-01 15:33:59 -04003// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +01006//
David Neto9fc86582016-09-01 15:33:59 -04007// http://www.apache.org/licenses/LICENSE-2.0
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +01008//
David Neto9fc86582016-09-01 15:33:59 -04009// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010014
dan sinclaireda2cfb2018-08-03 15:06:09 -040015#include "source/opcode.h"
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010016
17#include <assert.h>
18#include <string.h>
19
David Neto5a0b5ca2016-12-09 14:01:43 -050020#include <algorithm>
Lei Zhang972788b2015-11-12 13:48:30 -050021#include <cstdlib>
22
dan sinclaireda2cfb2018-08-03 15:06:09 -040023#include "source/instruction.h"
24#include "source/macro.h"
25#include "source/spirv_constant.h"
26#include "source/spirv_endian.h"
27#include "source/spirv_target_env.h"
David Neto5a703352016-02-17 14:44:00 -050028#include "spirv-tools/libspirv.h"
Lei Zhang923f6c12015-11-11 12:45:23 -050029
David Neto78c3b432015-08-27 13:03:52 -040030namespace {
Lei Zhang16981f82017-09-21 17:24:57 -040031struct OpcodeDescPtrLen {
32 const spv_opcode_desc_t* ptr;
33 uint32_t len;
34};
David Neto78c3b432015-08-27 13:03:52 -040035
dan sinclaireda2cfb2018-08-03 15:06:09 -040036#include "core.insts-unified1.inc"
Lei Zhang16981f82017-09-21 17:24:57 -040037
Lei Zhang1ef6b192018-03-14 13:06:18 -040038static const spv_opcode_table_t kOpcodeTable = {ARRAY_SIZE(kOpcodeTableEntries),
39 kOpcodeTableEntries};
David Neto78c3b432015-08-27 13:03:52 -040040
David Neto5a0b5ca2016-12-09 14:01:43 -050041// Represents a vendor tool entry in the SPIR-V XML Regsitry.
42struct VendorTool {
43 uint32_t value;
44 const char* vendor;
Lei Zhang16981f82017-09-21 17:24:57 -040045 const char* tool; // Might be empty string.
46 const char* vendor_tool; // Combiantion of vendor and tool.
David Neto5a0b5ca2016-12-09 14:01:43 -050047};
48
49const VendorTool vendor_tools[] = {
50#include "generators.inc"
51};
52
Lei Zhanga94701d2015-09-14 10:05:37 -040053} // anonymous namespace
David Neto78c3b432015-08-27 13:03:52 -040054
David Neto5a0b5ca2016-12-09 14:01:43 -050055// TODO(dneto): Move this to another file. It doesn't belong with opcode
56// processing.
Lei Zhang1a0334e2015-11-02 09:41:20 -050057const char* spvGeneratorStr(uint32_t generator) {
David Neto5a0b5ca2016-12-09 14:01:43 -050058 auto where = std::find_if(
59 std::begin(vendor_tools), std::end(vendor_tools),
60 [generator](const VendorTool& vt) { return generator == vt.value; });
61 if (where != std::end(vendor_tools)) return where->vendor_tool;
62 return "Unknown";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010063}
64
Lei Zhangb36e7042015-10-28 13:40:52 -040065uint32_t spvOpcodeMake(uint16_t wordCount, SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010066 return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
67}
68
Lei Zhang6fa3f8a2016-03-31 17:26:31 -040069void spvOpcodeSplit(const uint32_t word, uint16_t* pWordCount,
70 uint16_t* pOpcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010071 if (pWordCount) {
72 *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
73 }
74 if (pOpcode) {
Lei Zhang6fa3f8a2016-03-31 17:26:31 -040075 *pOpcode = 0x0000ffff & word;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010076 }
77}
78
Lei Zhang1ef6b192018-03-14 13:06:18 -040079spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable, spv_target_env) {
Lei Zhang40056702015-09-11 14:31:27 -040080 if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010081
Lei Zhang16981f82017-09-21 17:24:57 -040082 // Descriptions of each opcode. Each entry describes the format of the
83 // instruction that follows a particular opcode.
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010084
Lei Zhang1ef6b192018-03-14 13:06:18 -040085 *pInstTable = &kOpcodeTable;
86 return SPV_SUCCESS;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010087}
88
Lei Zhang1ef6b192018-03-14 13:06:18 -040089spv_result_t spvOpcodeTableNameLookup(spv_target_env env,
90 const spv_opcode_table table,
Lei Zhang1a0334e2015-11-02 09:41:20 -050091 const char* name,
92 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -040093 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
94 if (!table) return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010095
96 // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
97 // preferable but the table requires sorting on the Opcode name, but it's
Lei Zhang1ef6b192018-03-14 13:06:18 -040098 // static const initialized and matches the order of the spec.
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010099 const size_t nameLength = strlen(name);
alan-baker45fb6962019-05-10 11:02:01 -0400100 const auto version = spvVersionForTargetEnv(env);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100101 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
Lei Zhang1ef6b192018-03-14 13:06:18 -0400102 const spv_opcode_desc_t& entry = table->entries[opcodeIndex];
103 // We considers the current opcode as available as long as
104 // 1. The target environment satisfies the minimal requirement of the
105 // opcode; or
106 // 2. There is at least one extension enabling this opcode.
107 //
108 // Note that the second rule assumes the extension enabling this instruction
109 // is indeed requested in the SPIR-V code; checking that should be
110 // validator's work.
alan-baker45fb6962019-05-10 11:02:01 -0400111 if (((version >= entry.minVersion && version <= entry.lastVersion) ||
David Neto8d65c892018-06-19 09:54:33 -0400112 entry.numExtensions > 0u || entry.numCapabilities > 0u) &&
Lei Zhang1ef6b192018-03-14 13:06:18 -0400113 nameLength == strlen(entry.name) &&
114 !strncmp(name, entry.name, nameLength)) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100115 // NOTE: Found out Opcode!
Lei Zhang1ef6b192018-03-14 13:06:18 -0400116 *pEntry = &entry;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100117 return SPV_SUCCESS;
118 }
119 }
120
121 return SPV_ERROR_INVALID_LOOKUP;
122}
123
Lei Zhang1ef6b192018-03-14 13:06:18 -0400124spv_result_t spvOpcodeTableValueLookup(spv_target_env env,
125 const spv_opcode_table table,
Lei Zhangb36e7042015-10-28 13:40:52 -0400126 const SpvOp opcode,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500127 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400128 if (!table) return SPV_ERROR_INVALID_TABLE;
129 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100130
Jesus Carabanof063f912017-10-27 15:28:50 +0300131 const auto beg = table->entries;
132 const auto end = table->entries + table->count;
Lei Zhang1ef6b192018-03-14 13:06:18 -0400133
alan-baker45fb6962019-05-10 11:02:01 -0400134 spv_opcode_desc_t needle = {"", opcode, 0, nullptr, 0, {},
135 false, false, 0, nullptr, ~0u, ~0u};
Lei Zhang1ef6b192018-03-14 13:06:18 -0400136
Jesus Carabanof063f912017-10-27 15:28:50 +0300137 auto comp = [](const spv_opcode_desc_t& lhs, const spv_opcode_desc_t& rhs) {
138 return lhs.opcode < rhs.opcode;
139 };
Lei Zhang1ef6b192018-03-14 13:06:18 -0400140
141 // We need to loop here because there can exist multiple symbols for the same
142 // opcode value, and they can be introduced in different target environments,
143 // which means they can have different minimal version requirements.
144 // Assumes the underlying table is already sorted ascendingly according to
145 // opcode value.
alan-baker45fb6962019-05-10 11:02:01 -0400146 const auto version = spvVersionForTargetEnv(env);
Lei Zhang1ef6b192018-03-14 13:06:18 -0400147 for (auto it = std::lower_bound(beg, end, needle, comp);
148 it != end && it->opcode == opcode; ++it) {
149 // We considers the current opcode as available as long as
150 // 1. The target environment satisfies the minimal requirement of the
151 // opcode; or
152 // 2. There is at least one extension enabling this opcode.
153 //
154 // Note that the second rule assumes the extension enabling this instruction
155 // is indeed requested in the SPIR-V code; checking that should be
156 // validator's work.
alan-baker45fb6962019-05-10 11:02:01 -0400157 if ((version >= it->minVersion && version <= it->lastVersion) ||
David Neto8d65c892018-06-19 09:54:33 -0400158 it->numExtensions > 0u || it->numCapabilities > 0u) {
Lei Zhang1ef6b192018-03-14 13:06:18 -0400159 *pEntry = it;
160 return SPV_SUCCESS;
161 }
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100162 }
163
164 return SPV_ERROR_INVALID_LOOKUP;
165}
166
Lei Zhang1a0334e2015-11-02 09:41:20 -0500167void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100168 const uint16_t wordCount, const spv_endianness_t endian,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500169 spv_instruction_t* pInst) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100170 pInst->opcode = opcode;
David Netob5dc8fc2015-10-06 16:22:00 -0400171 pInst->words.resize(wordCount);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100172 for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
173 pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
174 if (!wordIndex) {
175 uint16_t thisWordCount;
Lei Zhang6fa3f8a2016-03-31 17:26:31 -0400176 uint16_t thisOpcode;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100177 spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
Lei Zhang6fa3f8a2016-03-31 17:26:31 -0400178 assert(opcode == static_cast<SpvOp>(thisOpcode) &&
179 wordCount == thisWordCount && "Endianness failed!");
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100180 }
181 }
182}
183
Steven Perron4a804972020-02-20 14:07:57 -0500184const char* spvOpcodeString(const uint32_t opcode) {
Lei Zhang1ef6b192018-03-14 13:06:18 -0400185 const auto beg = kOpcodeTableEntries;
186 const auto end = kOpcodeTableEntries + ARRAY_SIZE(kOpcodeTableEntries);
Ricardo Garciadea10402020-02-21 21:06:46 +0100187 spv_opcode_desc_t needle = {"", static_cast<SpvOp>(opcode),
Steven Perron4a804972020-02-20 14:07:57 -0500188 0, nullptr,
189 0, {},
190 false, false,
191 0, nullptr,
192 ~0u, ~0u};
Jesus Carabanof063f912017-10-27 15:28:50 +0300193 auto comp = [](const spv_opcode_desc_t& lhs, const spv_opcode_desc_t& rhs) {
194 return lhs.opcode < rhs.opcode;
195 };
Lei Zhang1ef6b192018-03-14 13:06:18 -0400196 auto it = std::lower_bound(beg, end, needle, comp);
Diego Novillod2938e42017-11-08 12:40:02 -0500197 if (it != end && it->opcode == opcode) {
Jesus Carabanof063f912017-10-27 15:28:50 +0300198 return it->name;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100199 }
Lei Zhang16981f82017-09-21 17:24:57 -0400200
Lei Zhang4f293b72016-03-21 16:36:14 -0400201 assert(0 && "Unreachable!");
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100202 return "unknown";
203}
204
Lei Zhangb36e7042015-10-28 13:40:52 -0400205int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100206 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400207 case SpvOpTypeInt:
208 case SpvOpTypeFloat:
Dejan Mircevski276a7242016-01-21 15:55:43 -0500209 case SpvOpTypeBool:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100210 return true;
211 default:
212 return false;
213 }
214}
215
Alan Baker0a2ee652018-03-23 14:18:54 -0400216int32_t spvOpcodeIsSpecConstant(const SpvOp opcode) {
217 switch (opcode) {
218 case SpvOpSpecConstantTrue:
219 case SpvOpSpecConstantFalse:
220 case SpvOpSpecConstant:
221 case SpvOpSpecConstantComposite:
222 case SpvOpSpecConstantOp:
223 return true;
224 default:
225 return false;
226 }
227}
228
Lei Zhangb36e7042015-10-28 13:40:52 -0400229int32_t spvOpcodeIsConstant(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100230 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400231 case SpvOpConstantTrue:
232 case SpvOpConstantFalse:
233 case SpvOpConstant:
234 case SpvOpConstantComposite:
235 case SpvOpConstantSampler:
Lei Zhangb36e7042015-10-28 13:40:52 -0400236 case SpvOpConstantNull:
237 case SpvOpSpecConstantTrue:
238 case SpvOpSpecConstantFalse:
239 case SpvOpSpecConstant:
240 case SpvOpSpecConstantComposite:
Dejan Mircevski3fb26762016-04-04 15:55:05 -0400241 case SpvOpSpecConstantOp:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100242 return true;
243 default:
244 return false;
245 }
246}
247
David Neto1f3fb502016-09-14 11:57:20 -0400248bool spvOpcodeIsConstantOrUndef(const SpvOp opcode) {
249 return opcode == SpvOpUndef || spvOpcodeIsConstant(opcode);
250}
251
Aliya Pazylbekovaedb52642017-02-24 20:43:28 -0500252bool spvOpcodeIsScalarSpecConstant(const SpvOp opcode) {
253 switch (opcode) {
254 case SpvOpSpecConstantTrue:
255 case SpvOpSpecConstantFalse:
256 case SpvOpSpecConstant:
257 return true;
258 default:
259 return false;
260 }
261}
262
Lei Zhangb36e7042015-10-28 13:40:52 -0400263int32_t spvOpcodeIsComposite(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100264 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400265 case SpvOpTypeVector:
266 case SpvOpTypeMatrix:
267 case SpvOpTypeArray:
268 case SpvOpTypeStruct:
Jeff Bolz002ef362019-02-25 16:43:11 -0600269 case SpvOpTypeCooperativeMatrixNV:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100270 return true;
271 default:
272 return false;
273 }
274}
275
Ehsan Nasiri23af06c2017-02-01 15:37:39 -0500276bool spvOpcodeReturnsLogicalVariablePointer(const SpvOp opcode) {
277 switch (opcode) {
278 case SpvOpVariable:
279 case SpvOpAccessChain:
280 case SpvOpInBoundsAccessChain:
281 case SpvOpFunctionParameter:
282 case SpvOpImageTexelPointer:
283 case SpvOpCopyObject:
284 case SpvOpSelect:
285 case SpvOpPhi:
286 case SpvOpFunctionCall:
287 case SpvOpPtrAccessChain:
288 case SpvOpLoad:
289 case SpvOpConstantNull:
290 return true;
291 default:
292 return false;
293 }
294}
295
Florian Ziesche66fcb452016-03-02 22:17:54 +0100296int32_t spvOpcodeReturnsLogicalPointer(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100297 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400298 case SpvOpVariable:
299 case SpvOpAccessChain:
300 case SpvOpInBoundsAccessChain:
301 case SpvOpFunctionParameter:
Florian Ziesche66fcb452016-03-02 22:17:54 +0100302 case SpvOpImageTexelPointer:
303 case SpvOpCopyObject:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100304 return true;
305 default:
306 return false;
307 }
308}
309
Lei Zhangb36e7042015-10-28 13:40:52 -0400310int32_t spvOpcodeGeneratesType(SpvOp op) {
Lei Zhang1a0334e2015-11-02 09:41:20 -0500311 switch (op) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400312 case SpvOpTypeVoid:
313 case SpvOpTypeBool:
314 case SpvOpTypeInt:
315 case SpvOpTypeFloat:
316 case SpvOpTypeVector:
317 case SpvOpTypeMatrix:
318 case SpvOpTypeImage:
319 case SpvOpTypeSampler:
320 case SpvOpTypeSampledImage:
321 case SpvOpTypeArray:
322 case SpvOpTypeRuntimeArray:
323 case SpvOpTypeStruct:
324 case SpvOpTypeOpaque:
325 case SpvOpTypePointer:
326 case SpvOpTypeFunction:
327 case SpvOpTypeEvent:
328 case SpvOpTypeDeviceEvent:
329 case SpvOpTypeReserveId:
330 case SpvOpTypeQueue:
331 case SpvOpTypePipe:
Andrey Tuganov4ef3b3e2017-02-28 11:53:47 -0500332 case SpvOpTypePipeStorage:
333 case SpvOpTypeNamedBarrier:
alelenv1c1e7492018-10-25 11:07:46 -0700334 case SpvOpTypeAccelerationStructureNV:
Jeff Bolz002ef362019-02-25 16:43:11 -0600335 case SpvOpTypeCooperativeMatrixNV:
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400336 return true;
David Netoaef608c2015-11-02 14:59:02 -0500337 default:
338 // In particular, OpTypeForwardPointer does not generate a type,
339 // but declares a storage class for a pointer type generated
340 // by a different instruction.
341 break;
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400342 }
343 return 0;
344}
Steven Perroneb4653a2017-11-13 15:31:43 -0500345
346bool spvOpcodeIsDecoration(const SpvOp opcode) {
Steven Perron28c41552017-11-10 20:26:55 -0500347 switch (opcode) {
Steven Perroneb4653a2017-11-13 15:31:43 -0500348 case SpvOpDecorate:
349 case SpvOpDecorateId:
350 case SpvOpMemberDecorate:
351 case SpvOpGroupDecorate:
352 case SpvOpGroupMemberDecorate:
David Neto5f69f752018-03-05 13:34:13 -0500353 case SpvOpDecorateStringGOOGLE:
354 case SpvOpMemberDecorateStringGOOGLE:
Steven Perroneb4653a2017-11-13 15:31:43 -0500355 return true;
356 default:
357 break;
358 }
359 return false;
360}
Steven Perron28c41552017-11-10 20:26:55 -0500361
362bool spvOpcodeIsLoad(const SpvOp opcode) {
363 switch (opcode) {
364 case SpvOpLoad:
365 case SpvOpImageSampleExplicitLod:
366 case SpvOpImageSampleImplicitLod:
367 case SpvOpImageSampleDrefImplicitLod:
368 case SpvOpImageSampleDrefExplicitLod:
369 case SpvOpImageSampleProjImplicitLod:
370 case SpvOpImageSampleProjExplicitLod:
371 case SpvOpImageSampleProjDrefImplicitLod:
372 case SpvOpImageSampleProjDrefExplicitLod:
373 case SpvOpImageFetch:
374 case SpvOpImageGather:
375 case SpvOpImageDrefGather:
376 case SpvOpImageRead:
377 case SpvOpImageSparseSampleImplicitLod:
378 case SpvOpImageSparseSampleExplicitLod:
379 case SpvOpImageSparseSampleDrefExplicitLod:
380 case SpvOpImageSparseSampleDrefImplicitLod:
381 case SpvOpImageSparseFetch:
382 case SpvOpImageSparseGather:
383 case SpvOpImageSparseDrefGather:
384 case SpvOpImageSparseRead:
385 return true;
386 default:
387 return false;
388 }
389}
390
Diego Novillo74327842017-11-17 08:59:25 -0500391bool spvOpcodeIsBranch(SpvOp opcode) {
392 switch (opcode) {
393 case SpvOpBranch:
394 case SpvOpBranchConditional:
395 case SpvOpSwitch:
396 return true;
397 default:
398 return false;
399 }
400}
401
greg-lunarge5455642018-10-12 06:46:35 -0600402bool spvOpcodeIsAtomicWithLoad(const SpvOp opcode) {
Steven Perron28c41552017-11-10 20:26:55 -0500403 switch (opcode) {
404 case SpvOpAtomicLoad:
Steven Perron28c41552017-11-10 20:26:55 -0500405 case SpvOpAtomicExchange:
406 case SpvOpAtomicCompareExchange:
407 case SpvOpAtomicCompareExchangeWeak:
408 case SpvOpAtomicIIncrement:
409 case SpvOpAtomicIDecrement:
410 case SpvOpAtomicIAdd:
411 case SpvOpAtomicISub:
412 case SpvOpAtomicSMin:
413 case SpvOpAtomicUMin:
414 case SpvOpAtomicSMax:
415 case SpvOpAtomicUMax:
416 case SpvOpAtomicAnd:
417 case SpvOpAtomicOr:
418 case SpvOpAtomicXor:
419 case SpvOpAtomicFlagTestAndSet:
Steven Perron28c41552017-11-10 20:26:55 -0500420 return true;
421 default:
422 return false;
423 }
424}
Diego Novillo74327842017-11-17 08:59:25 -0500425
greg-lunarge5455642018-10-12 06:46:35 -0600426bool spvOpcodeIsAtomicOp(const SpvOp opcode) {
427 return (spvOpcodeIsAtomicWithLoad(opcode) || opcode == SpvOpAtomicStore ||
428 opcode == SpvOpAtomicFlagClear);
429}
430
Diego Novillo74327842017-11-17 08:59:25 -0500431bool spvOpcodeIsReturn(SpvOp opcode) {
432 switch (opcode) {
433 case SpvOpReturn:
434 case SpvOpReturnValue:
435 return true;
436 default:
437 return false;
438 }
439}
440
Diego Novillo5f100782018-01-03 15:25:03 -0500441bool spvOpcodeIsReturnOrAbort(SpvOp opcode) {
442 return spvOpcodeIsReturn(opcode) || opcode == SpvOpKill ||
443 opcode == SpvOpUnreachable;
444}
445
Diego Novillo74327842017-11-17 08:59:25 -0500446bool spvOpcodeIsBlockTerminator(SpvOp opcode) {
Diego Novillo5f100782018-01-03 15:25:03 -0500447 return spvOpcodeIsBranch(opcode) || spvOpcodeIsReturnOrAbort(opcode);
Diego Novillo74327842017-11-17 08:59:25 -0500448}
Steven Perron79a00642017-12-11 13:10:24 -0500449
450bool spvOpcodeIsBaseOpaqueType(SpvOp opcode) {
451 switch (opcode) {
452 case SpvOpTypeImage:
453 case SpvOpTypeSampler:
454 case SpvOpTypeSampledImage:
455 case SpvOpTypeOpaque:
456 case SpvOpTypeEvent:
457 case SpvOpTypeDeviceEvent:
458 case SpvOpTypeReserveId:
459 case SpvOpTypeQueue:
460 case SpvOpTypePipe:
461 case SpvOpTypeForwardPointer:
462 case SpvOpTypePipeStorage:
463 case SpvOpTypeNamedBarrier:
464 return true;
465 default:
466 return false;
467 }
468}
Alan Baker09c206b2018-04-17 10:18:59 -0400469
470bool spvOpcodeIsNonUniformGroupOperation(SpvOp opcode) {
471 switch (opcode) {
472 case SpvOpGroupNonUniformElect:
473 case SpvOpGroupNonUniformAll:
474 case SpvOpGroupNonUniformAny:
475 case SpvOpGroupNonUniformAllEqual:
476 case SpvOpGroupNonUniformBroadcast:
477 case SpvOpGroupNonUniformBroadcastFirst:
478 case SpvOpGroupNonUniformBallot:
479 case SpvOpGroupNonUniformInverseBallot:
480 case SpvOpGroupNonUniformBallotBitExtract:
481 case SpvOpGroupNonUniformBallotBitCount:
482 case SpvOpGroupNonUniformBallotFindLSB:
483 case SpvOpGroupNonUniformBallotFindMSB:
484 case SpvOpGroupNonUniformShuffle:
485 case SpvOpGroupNonUniformShuffleXor:
486 case SpvOpGroupNonUniformShuffleUp:
487 case SpvOpGroupNonUniformShuffleDown:
488 case SpvOpGroupNonUniformIAdd:
489 case SpvOpGroupNonUniformFAdd:
490 case SpvOpGroupNonUniformIMul:
491 case SpvOpGroupNonUniformFMul:
492 case SpvOpGroupNonUniformSMin:
493 case SpvOpGroupNonUniformUMin:
494 case SpvOpGroupNonUniformFMin:
495 case SpvOpGroupNonUniformSMax:
496 case SpvOpGroupNonUniformUMax:
497 case SpvOpGroupNonUniformFMax:
498 case SpvOpGroupNonUniformBitwiseAnd:
499 case SpvOpGroupNonUniformBitwiseOr:
500 case SpvOpGroupNonUniformBitwiseXor:
501 case SpvOpGroupNonUniformLogicalAnd:
502 case SpvOpGroupNonUniformLogicalOr:
503 case SpvOpGroupNonUniformLogicalXor:
504 case SpvOpGroupNonUniformQuadBroadcast:
505 case SpvOpGroupNonUniformQuadSwap:
506 return true;
507 default:
508 return false;
509 }
510}
Steven Perron2c0ce872018-04-23 11:13:07 -0400511
512bool spvOpcodeIsScalarizable(SpvOp opcode) {
513 switch (opcode) {
514 case SpvOpPhi:
515 case SpvOpCopyObject:
516 case SpvOpConvertFToU:
517 case SpvOpConvertFToS:
518 case SpvOpConvertSToF:
519 case SpvOpConvertUToF:
520 case SpvOpUConvert:
521 case SpvOpSConvert:
522 case SpvOpFConvert:
523 case SpvOpQuantizeToF16:
524 case SpvOpVectorInsertDynamic:
525 case SpvOpSNegate:
526 case SpvOpFNegate:
527 case SpvOpIAdd:
528 case SpvOpFAdd:
529 case SpvOpISub:
530 case SpvOpFSub:
531 case SpvOpIMul:
532 case SpvOpFMul:
533 case SpvOpUDiv:
534 case SpvOpSDiv:
535 case SpvOpFDiv:
536 case SpvOpUMod:
537 case SpvOpSRem:
538 case SpvOpSMod:
539 case SpvOpFRem:
540 case SpvOpFMod:
541 case SpvOpVectorTimesScalar:
542 case SpvOpIAddCarry:
543 case SpvOpISubBorrow:
544 case SpvOpUMulExtended:
545 case SpvOpSMulExtended:
546 case SpvOpShiftRightLogical:
547 case SpvOpShiftRightArithmetic:
548 case SpvOpShiftLeftLogical:
549 case SpvOpBitwiseOr:
550 case SpvOpBitwiseAnd:
551 case SpvOpNot:
552 case SpvOpBitFieldInsert:
553 case SpvOpBitFieldSExtract:
554 case SpvOpBitFieldUExtract:
555 case SpvOpBitReverse:
556 case SpvOpBitCount:
557 case SpvOpIsNan:
558 case SpvOpIsInf:
559 case SpvOpIsFinite:
560 case SpvOpIsNormal:
561 case SpvOpSignBitSet:
562 case SpvOpLessOrGreater:
563 case SpvOpOrdered:
564 case SpvOpUnordered:
565 case SpvOpLogicalEqual:
566 case SpvOpLogicalNotEqual:
567 case SpvOpLogicalOr:
568 case SpvOpLogicalAnd:
569 case SpvOpLogicalNot:
570 case SpvOpSelect:
571 case SpvOpIEqual:
572 case SpvOpINotEqual:
573 case SpvOpUGreaterThan:
574 case SpvOpSGreaterThan:
575 case SpvOpUGreaterThanEqual:
576 case SpvOpSGreaterThanEqual:
577 case SpvOpULessThan:
578 case SpvOpSLessThan:
579 case SpvOpULessThanEqual:
580 case SpvOpSLessThanEqual:
581 case SpvOpFOrdEqual:
582 case SpvOpFUnordEqual:
583 case SpvOpFOrdNotEqual:
584 case SpvOpFUnordNotEqual:
585 case SpvOpFOrdLessThan:
586 case SpvOpFUnordLessThan:
587 case SpvOpFOrdGreaterThan:
588 case SpvOpFUnordGreaterThan:
589 case SpvOpFOrdLessThanEqual:
590 case SpvOpFUnordLessThanEqual:
591 case SpvOpFOrdGreaterThanEqual:
592 case SpvOpFUnordGreaterThanEqual:
593 return true;
594 default:
595 return false;
596 }
597}
Ryan Harrison11c7a9e2018-11-20 16:12:28 -0500598
599bool spvOpcodeIsDebug(SpvOp opcode) {
600 switch (opcode) {
601 case SpvOpName:
602 case SpvOpMemberName:
603 case SpvOpSource:
604 case SpvOpSourceContinued:
605 case SpvOpSourceExtension:
606 case SpvOpString:
607 case SpvOpLine:
608 case SpvOpNoLine:
609 return true;
610 default:
611 return false;
612 }
613}
Ryan Harrisone5455222019-03-14 13:34:33 -0400614
615std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode) {
616 switch (opcode) {
617 case SpvOpMemoryBarrier:
618 return {1};
619 case SpvOpAtomicStore:
620 case SpvOpControlBarrier:
621 case SpvOpAtomicFlagClear:
622 case SpvOpMemoryNamedBarrier:
623 return {2};
624 case SpvOpAtomicLoad:
625 case SpvOpAtomicExchange:
626 case SpvOpAtomicIIncrement:
627 case SpvOpAtomicIDecrement:
628 case SpvOpAtomicIAdd:
629 case SpvOpAtomicISub:
630 case SpvOpAtomicSMin:
631 case SpvOpAtomicUMin:
632 case SpvOpAtomicSMax:
633 case SpvOpAtomicUMax:
634 case SpvOpAtomicAnd:
635 case SpvOpAtomicOr:
636 case SpvOpAtomicXor:
637 case SpvOpAtomicFlagTestAndSet:
638 return {4};
639 case SpvOpAtomicCompareExchange:
640 case SpvOpAtomicCompareExchangeWeak:
641 return {4, 5};
642 default:
643 return {};
644 }
645}