blob: f82c36e0784e71bcdd2c57b19ac3a05c79dc25e4 [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.
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040039namespace v1_0 {
Dejan Mircevskie26fdc62016-04-07 14:09:48 -040040#include "operand.kinds-1-0.inc"
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040041} // namespace v1_0
42namespace v1_1 {
43#include "operand.kinds-1-1.inc"
44} // namespace v1_1
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010045
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040046spv_result_t spvOperandTableGet(spv_operand_table* pOperandTable,
47 spv_target_env env) {
Lei Zhang40056702015-09-11 14:31:27 -040048 if (!pOperandTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010049
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040050 static const spv_operand_table_t table_1_0 = {
51 ARRAY_SIZE(v1_0::pygen_variable_OperandInfoTable),
52 v1_0::pygen_variable_OperandInfoTable};
53 static const spv_operand_table_t table_1_1 = {
54 ARRAY_SIZE(v1_1::pygen_variable_OperandInfoTable),
55 v1_1::pygen_variable_OperandInfoTable};
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010056
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040057 switch (env) {
58 case SPV_ENV_UNIVERSAL_1_0:
59 case SPV_ENV_VULKAN_1_0:
60 *pOperandTable = &table_1_0;
61 return SPV_SUCCESS;
62 case SPV_ENV_UNIVERSAL_1_1:
63 *pOperandTable = &table_1_1;
64 return SPV_SUCCESS;
65 }
66 assert(0 && "Unknown spv_target_env in spvOperandTableGet()");
67 return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010068}
69
Dejan Mircevski3e6b2df2016-01-07 11:00:38 -050070#undef ARRAY_SIZE
71
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010072spv_result_t spvOperandTableNameLookup(const spv_operand_table table,
73 const spv_operand_type_t type,
David Neto388c40d2015-09-16 16:42:56 -040074 const char* name,
75 const size_t nameLength,
76 spv_operand_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -040077 if (!table) return SPV_ERROR_INVALID_TABLE;
78 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010079
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010080 for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
81 if (type == table->types[typeIndex].type) {
82 for (uint64_t operandIndex = 0;
83 operandIndex < table->types[typeIndex].count; ++operandIndex) {
84 if (nameLength ==
85 strlen(table->types[typeIndex].entries[operandIndex].name) &&
86 !strncmp(table->types[typeIndex].entries[operandIndex].name, name,
David Neto388c40d2015-09-16 16:42:56 -040087 nameLength)) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010088 *pEntry = &table->types[typeIndex].entries[operandIndex];
89 return SPV_SUCCESS;
90 }
91 }
92 }
93 }
94
95 return SPV_ERROR_INVALID_LOOKUP;
96}
97
98spv_result_t spvOperandTableValueLookup(const spv_operand_table table,
99 const spv_operand_type_t type,
100 const uint32_t value,
Dejan Mircevski50babb22015-09-29 10:56:32 -0400101 spv_operand_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400102 if (!table) return SPV_ERROR_INVALID_TABLE;
103 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100104
105 for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
106 if (type == table->types[typeIndex].type) {
107 for (uint64_t operandIndex = 0;
108 operandIndex < table->types[typeIndex].count; ++operandIndex) {
109 if (value == table->types[typeIndex].entries[operandIndex].value) {
110 *pEntry = &table->types[typeIndex].entries[operandIndex];
111 return SPV_SUCCESS;
112 }
113 }
114 }
115 }
116
117 return SPV_ERROR_INVALID_LOOKUP;
118}
119
Dejan Mircevski50babb22015-09-29 10:56:32 -0400120const char* spvOperandTypeStr(spv_operand_type_t type) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100121 switch (type) {
122 case SPV_OPERAND_TYPE_ID:
David Netofadbf622015-09-14 17:07:11 -0400123 case SPV_OPERAND_TYPE_OPTIONAL_ID:
David Netofadbf622015-09-14 17:07:11 -0400124 return "ID";
David Neto201caf72015-11-04 17:38:17 -0500125 case SPV_OPERAND_TYPE_TYPE_ID:
126 return "type ID";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100127 case SPV_OPERAND_TYPE_RESULT_ID:
128 return "result ID";
Lei Zhang6483bd72015-10-14 17:02:39 -0400129 case SPV_OPERAND_TYPE_LITERAL_INTEGER:
David Neto201caf72015-11-04 17:38:17 -0500130 case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER:
131 case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100132 return "literal number";
David Neto201caf72015-11-04 17:38:17 -0500133 case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
134 return "possibly multi-word literal integer";
135 case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
136 return "possibly multi-word literal number";
137 case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER:
138 return "extension instruction number";
David Neto0f166be2015-11-11 01:56:49 -0500139 case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER:
140 return "OpSpecConstantOp opcode";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100141 case SPV_OPERAND_TYPE_LITERAL_STRING:
David Neto201caf72015-11-04 17:38:17 -0500142 case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100143 return "literal string";
144 case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
Dejan Mircevskid2c81cf2015-10-09 11:06:10 -0400145 return "source language";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100146 case SPV_OPERAND_TYPE_EXECUTION_MODEL:
147 return "execution model";
148 case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
149 return "addressing model";
150 case SPV_OPERAND_TYPE_MEMORY_MODEL:
151 return "memory model";
152 case SPV_OPERAND_TYPE_EXECUTION_MODE:
153 return "execution mode";
154 case SPV_OPERAND_TYPE_STORAGE_CLASS:
155 return "storage class";
156 case SPV_OPERAND_TYPE_DIMENSIONALITY:
157 return "dimensionality";
158 case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
David Netod9ad0502015-11-24 18:37:24 -0500159 return "sampler addressing mode";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100160 case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
161 return "sampler filter mode";
David Netob30a0c52015-09-16 15:56:43 -0400162 case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT:
Dejan Mircevski971b3442015-10-13 12:54:47 -0400163 return "image format";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100164 case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
Dejan Mircevski355cc0c2015-10-13 15:02:03 -0400165 return "floating-point fast math mode";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100166 case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
Dejan Mircevski355cc0c2015-10-13 15:02:03 -0400167 return "floating-point rounding mode";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100168 case SPV_OPERAND_TYPE_LINKAGE_TYPE:
169 return "linkage type";
170 case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
David Neto2889a0c2016-02-15 13:50:00 -0500171 case SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100172 return "access qualifier";
173 case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
174 return "function parameter attribute";
175 case SPV_OPERAND_TYPE_DECORATION:
176 return "decoration";
177 case SPV_OPERAND_TYPE_BUILT_IN:
Dejan Mircevskid7b0f832015-10-13 15:39:38 -0400178 return "built-in";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100179 case SPV_OPERAND_TYPE_SELECTION_CONTROL:
180 return "selection control";
181 case SPV_OPERAND_TYPE_LOOP_CONTROL:
182 return "loop control";
183 case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
184 return "function control";
David Neto64a9be92015-11-18 15:48:32 -0500185 case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
David Netod9ad0502015-11-24 18:37:24 -0500186 return "memory semantics ID";
David Neto201caf72015-11-04 17:38:17 -0500187 case SPV_OPERAND_TYPE_MEMORY_ACCESS:
David Neto78c3b432015-08-27 13:03:52 -0400188 case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100189 return "memory access";
David Neto64a9be92015-11-18 15:48:32 -0500190 case SPV_OPERAND_TYPE_SCOPE_ID:
David Netod9ad0502015-11-24 18:37:24 -0500191 return "scope ID";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100192 case SPV_OPERAND_TYPE_GROUP_OPERATION:
193 return "group operation";
194 case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
195 return "kernel enqeue flags";
David Neto47994822015-08-27 13:11:01 -0400196 case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100197 return "kernel profiling info";
198 case SPV_OPERAND_TYPE_CAPABILITY:
199 return "capability";
David Neto201caf72015-11-04 17:38:17 -0500200 case SPV_OPERAND_TYPE_IMAGE:
David Netoee1b3bb2015-09-18 11:19:18 -0400201 case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
David Netod9ad0502015-11-24 18:37:24 -0500202 return "image";
David Neto201caf72015-11-04 17:38:17 -0500203 case SPV_OPERAND_TYPE_OPTIONAL_CIV:
204 return "context-insensitive value";
205
206 // The next values are for values returned from an instruction, not actually
207 // an operand. So the specific strings don't matter. But let's add them
208 // for completeness and ease of testing.
209 case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER:
210 return "image channel order";
211 case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE:
212 return "image channel data type";
213
David Neto78c3b432015-08-27 13:03:52 -0400214 case SPV_OPERAND_TYPE_NONE:
215 return "NONE";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100216 default:
217 assert(0 && "Unhandled operand type!");
218 break;
219 }
220 return "unknown";
221}
David Neto78c3b432015-08-27 13:03:52 -0400222
223void spvPrependOperandTypes(const spv_operand_type_t* types,
224 spv_operand_pattern_t* pattern) {
225 const spv_operand_type_t* endTypes;
Dejan Mircevski50babb22015-09-29 10:56:32 -0400226 for (endTypes = types; *endTypes != SPV_OPERAND_TYPE_NONE; ++endTypes)
David Neto78c3b432015-08-27 13:03:52 -0400227 ;
228 pattern->insert(pattern->begin(), types, endTypes);
229}
230
David Neto5bf88fc2015-09-17 17:06:10 -0400231void spvPrependOperandTypesForMask(const spv_operand_table operandTable,
232 const spv_operand_type_t type,
233 const uint32_t mask,
234 spv_operand_pattern_t* pattern) {
235 // Scan from highest bits to lowest bits because we will prepend in LIFO
236 // fashion, and we need the operands for lower order bits to appear first.
237 for (uint32_t candidate_bit = (1 << 31); candidate_bit; candidate_bit >>= 1) {
238 if (candidate_bit & mask) {
239 spv_operand_desc entry = nullptr;
240 if (SPV_SUCCESS == spvOperandTableValueLookup(operandTable, type,
241 candidate_bit, &entry)) {
242 spvPrependOperandTypes(entry->operandTypes, pattern);
243 }
244 }
245 }
246}
247
David Netob5267562016-02-02 12:05:34 -0500248bool spvOperandIsConcreteMask(spv_operand_type_t type) {
249 return SPV_OPERAND_TYPE_FIRST_CONCRETE_MASK_TYPE <= type &&
250 type <= SPV_OPERAND_TYPE_LAST_CONCRETE_MASK_TYPE;
251}
252
David Neto78c3b432015-08-27 13:03:52 -0400253bool spvOperandIsOptional(spv_operand_type_t type) {
David Neto201caf72015-11-04 17:38:17 -0500254 return SPV_OPERAND_TYPE_FIRST_OPTIONAL_TYPE <= type &&
255 type <= SPV_OPERAND_TYPE_LAST_OPTIONAL_TYPE;
David Neto78c3b432015-08-27 13:03:52 -0400256}
257
258bool spvOperandIsVariable(spv_operand_type_t type) {
David Neto201caf72015-11-04 17:38:17 -0500259 return SPV_OPERAND_TYPE_FIRST_VARIABLE_TYPE <= type &&
260 type <= SPV_OPERAND_TYPE_LAST_VARIABLE_TYPE;
David Neto78c3b432015-08-27 13:03:52 -0400261}
262
David Neto78c3b432015-08-27 13:03:52 -0400263bool spvExpandOperandSequenceOnce(spv_operand_type_t type,
264 spv_operand_pattern_t* pattern) {
265 switch (type) {
266 case SPV_OPERAND_TYPE_VARIABLE_ID:
267 pattern->insert(pattern->begin(), {SPV_OPERAND_TYPE_OPTIONAL_ID, type});
268 return true;
Lei Zhang6483bd72015-10-14 17:02:39 -0400269 case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER:
David Neto78c3b432015-08-27 13:03:52 -0400270 pattern->insert(pattern->begin(),
Lei Zhang6483bd72015-10-14 17:02:39 -0400271 {SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER, type});
David Neto78c3b432015-08-27 13:03:52 -0400272 return true;
Lei Zhang6483bd72015-10-14 17:02:39 -0400273 case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID:
David Neto201caf72015-11-04 17:38:17 -0500274 // Represents Zero or more (Literal number, Id) pairs,
275 // where the literal number must be a scalar integer.
David Neto78c3b432015-08-27 13:03:52 -0400276 pattern->insert(pattern->begin(),
David Neto201caf72015-11-04 17:38:17 -0500277 {SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER,
278 SPV_OPERAND_TYPE_ID, type});
David Neto78c3b432015-08-27 13:03:52 -0400279 return true;
Lei Zhang6483bd72015-10-14 17:02:39 -0400280 case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER:
David Neto561dc4e2015-09-25 14:23:29 -0400281 // Represents Zero or more (Id, Literal number) pairs.
David Neto201caf72015-11-04 17:38:17 -0500282 pattern->insert(pattern->begin(),
283 {SPV_OPERAND_TYPE_OPTIONAL_ID,
284 SPV_OPERAND_TYPE_LITERAL_INTEGER, type});
David Neto78c3b432015-08-27 13:03:52 -0400285 return true;
David Neto78c3b432015-08-27 13:03:52 -0400286 default:
287 break;
288 }
289 return false;
290}
291
Dejan Mircevski50babb22015-09-29 10:56:32 -0400292spv_operand_type_t spvTakeFirstMatchableOperand(
293 spv_operand_pattern_t* pattern) {
David Neto78c3b432015-08-27 13:03:52 -0400294 assert(!pattern->empty());
295 spv_operand_type_t result;
296 do {
297 result = pattern->front();
298 pattern->pop_front();
Dejan Mircevski50babb22015-09-29 10:56:32 -0400299 } while (spvExpandOperandSequenceOnce(result, pattern));
David Neto78c3b432015-08-27 13:03:52 -0400300 return result;
301}
Dejan Mircevski903f9d62015-09-28 17:04:39 -0400302
Dejan Mircevski897bff92015-09-29 10:38:18 -0400303spv_operand_pattern_t spvAlternatePatternFollowingImmediate(
304 const spv_operand_pattern_t& pattern) {
305 spv_operand_pattern_t alternatePattern;
306 for (const auto& operand : pattern) {
307 if (operand == SPV_OPERAND_TYPE_RESULT_ID) {
308 alternatePattern.push_back(operand);
309 alternatePattern.push_back(SPV_OPERAND_TYPE_OPTIONAL_CIV);
310 return alternatePattern;
Dejan Mircevski903f9d62015-09-28 17:04:39 -0400311 }
Dejan Mircevski897bff92015-09-29 10:38:18 -0400312 alternatePattern.push_back(SPV_OPERAND_TYPE_OPTIONAL_CIV);
Dejan Mircevski903f9d62015-09-28 17:04:39 -0400313 }
Dejan Mircevski897bff92015-09-29 10:38:18 -0400314 // No result-id found, so just expect CIVs.
315 return {SPV_OPERAND_TYPE_OPTIONAL_CIV};
Dejan Mircevski903f9d62015-09-28 17:04:39 -0400316}
Dejan Mircevski961f5dc2016-01-15 11:25:11 -0500317
318bool spvIsIdType(spv_operand_type_t type) {
319 switch (type) {
320 case SPV_OPERAND_TYPE_ID:
321 case SPV_OPERAND_TYPE_TYPE_ID:
322 case SPV_OPERAND_TYPE_RESULT_ID:
323 case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
324 case SPV_OPERAND_TYPE_SCOPE_ID:
325 return true;
326 default:
327 return false;
328 }
329 return false;
330}