blob: 5de3f4313c5402bdf5afb989f535b1de7be75227 [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//
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 "operand.h"
28
29#include <assert.h>
30#include <string.h>
31
David Netoba73a7c2016-01-06 13:08:39 -050032// Evaluates to the number of elements of array A.
33// If we could use constexpr, then we could make this a template function.
34// If the source arrays were std::array, then we could have used
35// std::array::size.
David Netodd8a6612016-02-14 13:55:50 -050036#define ARRAY_SIZE(A) (static_cast<uint32_t>(sizeof(A) / sizeof(A[0])))
David Netoba73a7c2016-01-06 13:08:39 -050037
Lei Zhang4f293b72016-03-21 16:36:14 -040038// Pull in operand info tables automatically generated from JSON grammar.
Lei Zhang80e416c2016-04-04 14:30:56 -040039#include "operand.kinds.inc"
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010040
Dejan Mircevski50babb22015-09-29 10:56:32 -040041spv_result_t spvOperandTableGet(spv_operand_table* pOperandTable) {
Lei Zhang40056702015-09-11 14:31:27 -040042 if (!pOperandTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010043
Lei Zhang4f293b72016-03-21 16:36:14 -040044 static const spv_operand_table_t table = {
45 ARRAY_SIZE(pygen_variable_OperandInfoTable),
46 pygen_variable_OperandInfoTable};
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010047
48 *pOperandTable = &table;
49
50 return SPV_SUCCESS;
51}
52
Dejan Mircevski3e6b2df2016-01-07 11:00:38 -050053#undef ARRAY_SIZE
54
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010055spv_result_t spvOperandTableNameLookup(const spv_operand_table table,
56 const spv_operand_type_t type,
David Neto388c40d2015-09-16 16:42:56 -040057 const char* name,
58 const size_t nameLength,
59 spv_operand_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -040060 if (!table) return SPV_ERROR_INVALID_TABLE;
61 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010062
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010063 for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
64 if (type == table->types[typeIndex].type) {
65 for (uint64_t operandIndex = 0;
66 operandIndex < table->types[typeIndex].count; ++operandIndex) {
67 if (nameLength ==
68 strlen(table->types[typeIndex].entries[operandIndex].name) &&
69 !strncmp(table->types[typeIndex].entries[operandIndex].name, name,
David Neto388c40d2015-09-16 16:42:56 -040070 nameLength)) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010071 *pEntry = &table->types[typeIndex].entries[operandIndex];
72 return SPV_SUCCESS;
73 }
74 }
75 }
76 }
77
78 return SPV_ERROR_INVALID_LOOKUP;
79}
80
81spv_result_t spvOperandTableValueLookup(const spv_operand_table table,
82 const spv_operand_type_t type,
83 const uint32_t value,
Dejan Mircevski50babb22015-09-29 10:56:32 -040084 spv_operand_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -040085 if (!table) return SPV_ERROR_INVALID_TABLE;
86 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010087
88 for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
89 if (type == table->types[typeIndex].type) {
90 for (uint64_t operandIndex = 0;
91 operandIndex < table->types[typeIndex].count; ++operandIndex) {
92 if (value == table->types[typeIndex].entries[operandIndex].value) {
93 *pEntry = &table->types[typeIndex].entries[operandIndex];
94 return SPV_SUCCESS;
95 }
96 }
97 }
98 }
99
100 return SPV_ERROR_INVALID_LOOKUP;
101}
102
Dejan Mircevski50babb22015-09-29 10:56:32 -0400103const char* spvOperandTypeStr(spv_operand_type_t type) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100104 switch (type) {
105 case SPV_OPERAND_TYPE_ID:
David Netofadbf622015-09-14 17:07:11 -0400106 case SPV_OPERAND_TYPE_OPTIONAL_ID:
David Netofadbf622015-09-14 17:07:11 -0400107 return "ID";
David Neto201caf72015-11-04 17:38:17 -0500108 case SPV_OPERAND_TYPE_TYPE_ID:
109 return "type ID";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100110 case SPV_OPERAND_TYPE_RESULT_ID:
111 return "result ID";
Lei Zhang6483bd72015-10-14 17:02:39 -0400112 case SPV_OPERAND_TYPE_LITERAL_INTEGER:
David Neto201caf72015-11-04 17:38:17 -0500113 case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER:
114 case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100115 return "literal number";
David Neto201caf72015-11-04 17:38:17 -0500116 case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
117 return "possibly multi-word literal integer";
118 case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
119 return "possibly multi-word literal number";
120 case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER:
121 return "extension instruction number";
David Neto0f166be2015-11-11 01:56:49 -0500122 case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER:
123 return "OpSpecConstantOp opcode";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100124 case SPV_OPERAND_TYPE_LITERAL_STRING:
David Neto201caf72015-11-04 17:38:17 -0500125 case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100126 return "literal string";
127 case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
Dejan Mircevskid2c81cf2015-10-09 11:06:10 -0400128 return "source language";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100129 case SPV_OPERAND_TYPE_EXECUTION_MODEL:
130 return "execution model";
131 case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
132 return "addressing model";
133 case SPV_OPERAND_TYPE_MEMORY_MODEL:
134 return "memory model";
135 case SPV_OPERAND_TYPE_EXECUTION_MODE:
136 return "execution mode";
137 case SPV_OPERAND_TYPE_STORAGE_CLASS:
138 return "storage class";
139 case SPV_OPERAND_TYPE_DIMENSIONALITY:
140 return "dimensionality";
141 case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
David Netod9ad0502015-11-24 18:37:24 -0500142 return "sampler addressing mode";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100143 case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
144 return "sampler filter mode";
David Netob30a0c52015-09-16 15:56:43 -0400145 case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT:
Dejan Mircevski971b3442015-10-13 12:54:47 -0400146 return "image format";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100147 case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
Dejan Mircevski355cc0c2015-10-13 15:02:03 -0400148 return "floating-point fast math mode";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100149 case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
Dejan Mircevski355cc0c2015-10-13 15:02:03 -0400150 return "floating-point rounding mode";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100151 case SPV_OPERAND_TYPE_LINKAGE_TYPE:
152 return "linkage type";
153 case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
David Neto2889a0c2016-02-15 13:50:00 -0500154 case SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100155 return "access qualifier";
156 case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
157 return "function parameter attribute";
158 case SPV_OPERAND_TYPE_DECORATION:
159 return "decoration";
160 case SPV_OPERAND_TYPE_BUILT_IN:
Dejan Mircevskid7b0f832015-10-13 15:39:38 -0400161 return "built-in";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100162 case SPV_OPERAND_TYPE_SELECTION_CONTROL:
163 return "selection control";
164 case SPV_OPERAND_TYPE_LOOP_CONTROL:
165 return "loop control";
166 case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
167 return "function control";
David Neto64a9be92015-11-18 15:48:32 -0500168 case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
David Netod9ad0502015-11-24 18:37:24 -0500169 return "memory semantics ID";
David Neto201caf72015-11-04 17:38:17 -0500170 case SPV_OPERAND_TYPE_MEMORY_ACCESS:
David Neto78c3b432015-08-27 13:03:52 -0400171 case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100172 return "memory access";
David Neto64a9be92015-11-18 15:48:32 -0500173 case SPV_OPERAND_TYPE_SCOPE_ID:
David Netod9ad0502015-11-24 18:37:24 -0500174 return "scope ID";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100175 case SPV_OPERAND_TYPE_GROUP_OPERATION:
176 return "group operation";
177 case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
178 return "kernel enqeue flags";
David Neto47994822015-08-27 13:11:01 -0400179 case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100180 return "kernel profiling info";
181 case SPV_OPERAND_TYPE_CAPABILITY:
182 return "capability";
David Neto201caf72015-11-04 17:38:17 -0500183 case SPV_OPERAND_TYPE_IMAGE:
David Netoee1b3bb2015-09-18 11:19:18 -0400184 case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
David Netod9ad0502015-11-24 18:37:24 -0500185 return "image";
David Neto201caf72015-11-04 17:38:17 -0500186 case SPV_OPERAND_TYPE_OPTIONAL_CIV:
187 return "context-insensitive value";
188
189 // The next values are for values returned from an instruction, not actually
190 // an operand. So the specific strings don't matter. But let's add them
191 // for completeness and ease of testing.
192 case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER:
193 return "image channel order";
194 case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE:
195 return "image channel data type";
196
David Neto78c3b432015-08-27 13:03:52 -0400197 case SPV_OPERAND_TYPE_NONE:
198 return "NONE";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100199 default:
200 assert(0 && "Unhandled operand type!");
201 break;
202 }
203 return "unknown";
204}
David Neto78c3b432015-08-27 13:03:52 -0400205
206void spvPrependOperandTypes(const spv_operand_type_t* types,
207 spv_operand_pattern_t* pattern) {
208 const spv_operand_type_t* endTypes;
Dejan Mircevski50babb22015-09-29 10:56:32 -0400209 for (endTypes = types; *endTypes != SPV_OPERAND_TYPE_NONE; ++endTypes)
David Neto78c3b432015-08-27 13:03:52 -0400210 ;
211 pattern->insert(pattern->begin(), types, endTypes);
212}
213
David Neto5bf88fc2015-09-17 17:06:10 -0400214void spvPrependOperandTypesForMask(const spv_operand_table operandTable,
215 const spv_operand_type_t type,
216 const uint32_t mask,
217 spv_operand_pattern_t* pattern) {
218 // Scan from highest bits to lowest bits because we will prepend in LIFO
219 // fashion, and we need the operands for lower order bits to appear first.
220 for (uint32_t candidate_bit = (1 << 31); candidate_bit; candidate_bit >>= 1) {
221 if (candidate_bit & mask) {
222 spv_operand_desc entry = nullptr;
223 if (SPV_SUCCESS == spvOperandTableValueLookup(operandTable, type,
224 candidate_bit, &entry)) {
225 spvPrependOperandTypes(entry->operandTypes, pattern);
226 }
227 }
228 }
229}
230
David Netob5267562016-02-02 12:05:34 -0500231bool spvOperandIsConcreteMask(spv_operand_type_t type) {
232 return SPV_OPERAND_TYPE_FIRST_CONCRETE_MASK_TYPE <= type &&
233 type <= SPV_OPERAND_TYPE_LAST_CONCRETE_MASK_TYPE;
234}
235
David Neto78c3b432015-08-27 13:03:52 -0400236bool spvOperandIsOptional(spv_operand_type_t type) {
David Neto201caf72015-11-04 17:38:17 -0500237 return SPV_OPERAND_TYPE_FIRST_OPTIONAL_TYPE <= type &&
238 type <= SPV_OPERAND_TYPE_LAST_OPTIONAL_TYPE;
David Neto78c3b432015-08-27 13:03:52 -0400239}
240
241bool spvOperandIsVariable(spv_operand_type_t type) {
David Neto201caf72015-11-04 17:38:17 -0500242 return SPV_OPERAND_TYPE_FIRST_VARIABLE_TYPE <= type &&
243 type <= SPV_OPERAND_TYPE_LAST_VARIABLE_TYPE;
David Neto78c3b432015-08-27 13:03:52 -0400244}
245
David Neto78c3b432015-08-27 13:03:52 -0400246bool spvExpandOperandSequenceOnce(spv_operand_type_t type,
247 spv_operand_pattern_t* pattern) {
248 switch (type) {
249 case SPV_OPERAND_TYPE_VARIABLE_ID:
250 pattern->insert(pattern->begin(), {SPV_OPERAND_TYPE_OPTIONAL_ID, type});
251 return true;
Lei Zhang6483bd72015-10-14 17:02:39 -0400252 case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER:
David Neto78c3b432015-08-27 13:03:52 -0400253 pattern->insert(pattern->begin(),
Lei Zhang6483bd72015-10-14 17:02:39 -0400254 {SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER, type});
David Neto78c3b432015-08-27 13:03:52 -0400255 return true;
Lei Zhang6483bd72015-10-14 17:02:39 -0400256 case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID:
David Neto201caf72015-11-04 17:38:17 -0500257 // Represents Zero or more (Literal number, Id) pairs,
258 // where the literal number must be a scalar integer.
David Neto78c3b432015-08-27 13:03:52 -0400259 pattern->insert(pattern->begin(),
David Neto201caf72015-11-04 17:38:17 -0500260 {SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER,
261 SPV_OPERAND_TYPE_ID, type});
David Neto78c3b432015-08-27 13:03:52 -0400262 return true;
Lei Zhang6483bd72015-10-14 17:02:39 -0400263 case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER:
David Neto561dc4e2015-09-25 14:23:29 -0400264 // Represents Zero or more (Id, Literal number) pairs.
David Neto201caf72015-11-04 17:38:17 -0500265 pattern->insert(pattern->begin(),
266 {SPV_OPERAND_TYPE_OPTIONAL_ID,
267 SPV_OPERAND_TYPE_LITERAL_INTEGER, type});
David Neto78c3b432015-08-27 13:03:52 -0400268 return true;
David Neto78c3b432015-08-27 13:03:52 -0400269 default:
270 break;
271 }
272 return false;
273}
274
Dejan Mircevski50babb22015-09-29 10:56:32 -0400275spv_operand_type_t spvTakeFirstMatchableOperand(
276 spv_operand_pattern_t* pattern) {
David Neto78c3b432015-08-27 13:03:52 -0400277 assert(!pattern->empty());
278 spv_operand_type_t result;
279 do {
280 result = pattern->front();
281 pattern->pop_front();
Dejan Mircevski50babb22015-09-29 10:56:32 -0400282 } while (spvExpandOperandSequenceOnce(result, pattern));
David Neto78c3b432015-08-27 13:03:52 -0400283 return result;
284}
Dejan Mircevski903f9d62015-09-28 17:04:39 -0400285
Dejan Mircevski897bff92015-09-29 10:38:18 -0400286spv_operand_pattern_t spvAlternatePatternFollowingImmediate(
287 const spv_operand_pattern_t& pattern) {
288 spv_operand_pattern_t alternatePattern;
289 for (const auto& operand : pattern) {
290 if (operand == SPV_OPERAND_TYPE_RESULT_ID) {
291 alternatePattern.push_back(operand);
292 alternatePattern.push_back(SPV_OPERAND_TYPE_OPTIONAL_CIV);
293 return alternatePattern;
Dejan Mircevski903f9d62015-09-28 17:04:39 -0400294 }
Dejan Mircevski897bff92015-09-29 10:38:18 -0400295 alternatePattern.push_back(SPV_OPERAND_TYPE_OPTIONAL_CIV);
Dejan Mircevski903f9d62015-09-28 17:04:39 -0400296 }
Dejan Mircevski897bff92015-09-29 10:38:18 -0400297 // No result-id found, so just expect CIVs.
298 return {SPV_OPERAND_TYPE_OPTIONAL_CIV};
Dejan Mircevski903f9d62015-09-28 17:04:39 -0400299}
Dejan Mircevski961f5dc2016-01-15 11:25:11 -0500300
301bool spvIsIdType(spv_operand_type_t type) {
302 switch (type) {
303 case SPV_OPERAND_TYPE_ID:
304 case SPV_OPERAND_TYPE_TYPE_ID:
305 case SPV_OPERAND_TYPE_RESULT_ID:
306 case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
307 case SPV_OPERAND_TYPE_SCOPE_ID:
308 return true;
309 default:
310 return false;
311 }
312 return false;
313}