/src/spirv-tools/source/operand.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2015-2020 The Khronos Group Inc. |
2 | | // Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights |
3 | | // reserved. |
4 | | // |
5 | | // 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 |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // 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. |
16 | | |
17 | | #include "source/operand.h" |
18 | | |
19 | | #include <assert.h> |
20 | | #include <string.h> |
21 | | |
22 | | #include <algorithm> |
23 | | |
24 | | #include "DebugInfo.h" |
25 | | #include "OpenCLDebugInfo100.h" |
26 | | #include "source/macro.h" |
27 | | #include "source/opcode.h" |
28 | | #include "source/spirv_constant.h" |
29 | | #include "source/spirv_target_env.h" |
30 | | |
31 | | // For now, assume unified1 contains up to SPIR-V 1.3 and no later |
32 | | // SPIR-V version. |
33 | | // TODO(dneto): Make one set of tables, but with version tags on a |
34 | | // per-item basis. https://github.com/KhronosGroup/SPIRV-Tools/issues/1195 |
35 | | |
36 | | #include "operand.kinds-unified1.inc" |
37 | | #include "spirv-tools/libspirv.h" |
38 | | |
39 | | static const spv_operand_table_t kOperandTable = { |
40 | | ARRAY_SIZE(pygen_variable_OperandInfoTable), |
41 | | pygen_variable_OperandInfoTable}; |
42 | | |
43 | | spv_result_t spvOperandTableGet(spv_operand_table* pOperandTable, |
44 | 56.2k | spv_target_env) { |
45 | 56.2k | if (!pOperandTable) return SPV_ERROR_INVALID_POINTER; |
46 | | |
47 | 56.2k | *pOperandTable = &kOperandTable; |
48 | 56.2k | return SPV_SUCCESS; |
49 | 56.2k | } |
50 | | |
51 | | spv_result_t spvOperandTableNameLookup(spv_target_env env, |
52 | | const spv_operand_table table, |
53 | | const spv_operand_type_t type, |
54 | | const char* name, |
55 | | const size_t nameLength, |
56 | 0 | spv_operand_desc* pEntry) { |
57 | 0 | if (!table) return SPV_ERROR_INVALID_TABLE; |
58 | 0 | if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER; |
59 | | |
60 | 0 | const auto version = spvVersionForTargetEnv(env); |
61 | 0 | for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) { |
62 | 0 | const auto& group = table->types[typeIndex]; |
63 | 0 | if (type != group.type) continue; |
64 | 0 | for (uint64_t index = 0; index < group.count; ++index) { |
65 | 0 | const auto& entry = group.entries[index]; |
66 | | // We consider the current operand as available as long as |
67 | | // 1. The target environment satisfies the minimal requirement of the |
68 | | // operand; or |
69 | | // 2. There is at least one extension enabling this operand; or |
70 | | // 3. There is at least one capability enabling this operand. |
71 | | // |
72 | | // Note that the second rule assumes the extension enabling this operand |
73 | | // is indeed requested in the SPIR-V code; checking that should be |
74 | | // validator's work. |
75 | 0 | if (nameLength == strlen(entry.name) && |
76 | 0 | !strncmp(entry.name, name, nameLength)) { |
77 | 0 | if ((version >= entry.minVersion && version <= entry.lastVersion) || |
78 | 0 | entry.numExtensions > 0u || entry.numCapabilities > 0u) { |
79 | 0 | *pEntry = &entry; |
80 | 0 | return SPV_SUCCESS; |
81 | 0 | } else { |
82 | | // if there is no extension/capability then the version is wrong |
83 | 0 | return SPV_ERROR_WRONG_VERSION; |
84 | 0 | } |
85 | 0 | } |
86 | 0 | } |
87 | 0 | } |
88 | | |
89 | 0 | return SPV_ERROR_INVALID_LOOKUP; |
90 | 0 | } |
91 | | |
92 | | spv_result_t spvOperandTableValueLookup(spv_target_env env, |
93 | | const spv_operand_table table, |
94 | | const spv_operand_type_t type, |
95 | | const uint32_t value, |
96 | 2.40M | spv_operand_desc* pEntry) { |
97 | 2.40M | if (!table) return SPV_ERROR_INVALID_TABLE; |
98 | 2.40M | if (!pEntry) return SPV_ERROR_INVALID_POINTER; |
99 | | |
100 | 2.40M | spv_operand_desc_t needle = {"", value, 0, nullptr, 0, nullptr, {}, ~0u, ~0u}; |
101 | | |
102 | 12.7M | auto comp = [](const spv_operand_desc_t& lhs, const spv_operand_desc_t& rhs) { |
103 | 12.7M | return lhs.value < rhs.value; |
104 | 12.7M | }; |
105 | | |
106 | 62.9M | for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) { |
107 | 62.7M | const auto& group = table->types[typeIndex]; |
108 | 62.7M | if (type != group.type) continue; |
109 | | |
110 | 2.18M | const auto beg = group.entries; |
111 | 2.18M | const auto end = group.entries + group.count; |
112 | | |
113 | | // We need to loop here because there can exist multiple symbols for the |
114 | | // same operand value, and they can be introduced in different target |
115 | | // environments, which means they can have different minimal version |
116 | | // requirements. For example, SubgroupEqMaskKHR can exist in any SPIR-V |
117 | | // version as long as the SPV_KHR_shader_ballot extension is there; but |
118 | | // starting from SPIR-V 1.3, SubgroupEqMask, which has the same numeric |
119 | | // value as SubgroupEqMaskKHR, is available in core SPIR-V without extension |
120 | | // requirements. |
121 | | // Assumes the underlying table is already sorted ascendingly according to |
122 | | // opcode value. |
123 | 2.18M | const auto version = spvVersionForTargetEnv(env); |
124 | 2.18M | for (auto it = std::lower_bound(beg, end, needle, comp); |
125 | 2.18M | it != end && it->value == value; ++it) { |
126 | | // We consider the current operand as available as long as |
127 | | // 1. The target environment satisfies the minimal requirement of the |
128 | | // operand; or |
129 | | // 2. There is at least one extension enabling this operand; or |
130 | | // 3. There is at least one capability enabling this operand. |
131 | | // |
132 | | // Note that the second rule assumes the extension enabling this operand |
133 | | // is indeed requested in the SPIR-V code; checking that should be |
134 | | // validator's work. |
135 | 2.18M | if ((version >= it->minVersion && version <= it->lastVersion) || |
136 | 2.18M | it->numExtensions > 0u || it->numCapabilities > 0u) { |
137 | 2.18M | *pEntry = it; |
138 | 2.18M | return SPV_SUCCESS; |
139 | 2.18M | } |
140 | 2.18M | } |
141 | 2.18M | } |
142 | | |
143 | 211k | return SPV_ERROR_INVALID_LOOKUP; |
144 | 2.40M | } |
145 | | |
146 | 393 | const char* spvOperandTypeStr(spv_operand_type_t type) { |
147 | 393 | switch (type) { |
148 | 78 | case SPV_OPERAND_TYPE_ID: |
149 | 97 | case SPV_OPERAND_TYPE_OPTIONAL_ID: |
150 | 97 | return "ID"; |
151 | 15 | case SPV_OPERAND_TYPE_TYPE_ID: |
152 | 15 | return "type ID"; |
153 | 39 | case SPV_OPERAND_TYPE_RESULT_ID: |
154 | 39 | return "result ID"; |
155 | 9 | case SPV_OPERAND_TYPE_LITERAL_INTEGER: |
156 | 19 | case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER: |
157 | 19 | case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER: |
158 | 19 | return "literal number"; |
159 | 24 | case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER: |
160 | 24 | return "possibly multi-word literal integer"; |
161 | 3 | case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER: |
162 | 3 | return "possibly multi-word literal number"; |
163 | 0 | case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: |
164 | 0 | return "extension instruction number"; |
165 | 41 | case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: |
166 | 41 | return "OpSpecConstantOp opcode"; |
167 | 10 | case SPV_OPERAND_TYPE_LITERAL_STRING: |
168 | 12 | case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING: |
169 | 12 | return "literal string"; |
170 | 4 | case SPV_OPERAND_TYPE_SOURCE_LANGUAGE: |
171 | 4 | return "source language"; |
172 | 4 | case SPV_OPERAND_TYPE_EXECUTION_MODEL: |
173 | 4 | return "execution model"; |
174 | 10 | case SPV_OPERAND_TYPE_ADDRESSING_MODEL: |
175 | 10 | return "addressing model"; |
176 | 3 | case SPV_OPERAND_TYPE_MEMORY_MODEL: |
177 | 3 | return "memory model"; |
178 | 1 | case SPV_OPERAND_TYPE_EXECUTION_MODE: |
179 | 1 | return "execution mode"; |
180 | 3 | case SPV_OPERAND_TYPE_STORAGE_CLASS: |
181 | 3 | return "storage class"; |
182 | 0 | case SPV_OPERAND_TYPE_DIMENSIONALITY: |
183 | 0 | return "dimensionality"; |
184 | 0 | case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE: |
185 | 0 | return "sampler addressing mode"; |
186 | 0 | case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE: |
187 | 0 | return "sampler filter mode"; |
188 | 1 | case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT: |
189 | 1 | return "image format"; |
190 | 1 | case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE: |
191 | 1 | return "floating-point fast math mode"; |
192 | 2 | case SPV_OPERAND_TYPE_FP_ROUNDING_MODE: |
193 | 2 | return "floating-point rounding mode"; |
194 | 0 | case SPV_OPERAND_TYPE_LINKAGE_TYPE: |
195 | 0 | return "linkage type"; |
196 | 3 | case SPV_OPERAND_TYPE_ACCESS_QUALIFIER: |
197 | 3 | case SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER: |
198 | 3 | return "access qualifier"; |
199 | 0 | case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE: |
200 | 0 | return "function parameter attribute"; |
201 | 1 | case SPV_OPERAND_TYPE_DECORATION: |
202 | 1 | return "decoration"; |
203 | 0 | case SPV_OPERAND_TYPE_BUILT_IN: |
204 | 0 | return "built-in"; |
205 | 20 | case SPV_OPERAND_TYPE_SELECTION_CONTROL: |
206 | 20 | return "selection control"; |
207 | 5 | case SPV_OPERAND_TYPE_LOOP_CONTROL: |
208 | 5 | return "loop control"; |
209 | 5 | case SPV_OPERAND_TYPE_FUNCTION_CONTROL: |
210 | 5 | return "function control"; |
211 | 7 | case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID: |
212 | 7 | return "memory semantics ID"; |
213 | 11 | case SPV_OPERAND_TYPE_MEMORY_ACCESS: |
214 | 11 | case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS: |
215 | 11 | return "memory access"; |
216 | 0 | case SPV_OPERAND_TYPE_FRAGMENT_SHADING_RATE: |
217 | 0 | return "shading rate"; |
218 | 16 | case SPV_OPERAND_TYPE_SCOPE_ID: |
219 | 16 | return "scope ID"; |
220 | 9 | case SPV_OPERAND_TYPE_GROUP_OPERATION: |
221 | 9 | return "group operation"; |
222 | 0 | case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS: |
223 | 0 | return "kernel enqeue flags"; |
224 | 0 | case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO: |
225 | 0 | return "kernel profiling info"; |
226 | 17 | case SPV_OPERAND_TYPE_CAPABILITY: |
227 | 17 | return "capability"; |
228 | 0 | case SPV_OPERAND_TYPE_RAY_FLAGS: |
229 | 0 | return "ray flags"; |
230 | 0 | case SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION: |
231 | 0 | return "ray query intersection"; |
232 | 0 | case SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE: |
233 | 0 | return "ray query committed intersection type"; |
234 | 0 | case SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE: |
235 | 0 | return "ray query candidate intersection type"; |
236 | 1 | case SPV_OPERAND_TYPE_PACKED_VECTOR_FORMAT: |
237 | 1 | case SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT: |
238 | 1 | return "packed vector format"; |
239 | 13 | case SPV_OPERAND_TYPE_IMAGE: |
240 | 13 | case SPV_OPERAND_TYPE_OPTIONAL_IMAGE: |
241 | 13 | return "image"; |
242 | 0 | case SPV_OPERAND_TYPE_OPTIONAL_CIV: |
243 | 0 | return "context-insensitive value"; |
244 | 2 | case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS: |
245 | 2 | return "debug info flags"; |
246 | 2 | case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING: |
247 | 2 | return "debug base type encoding"; |
248 | 0 | case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE: |
249 | 0 | return "debug composite type"; |
250 | 0 | case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER: |
251 | 0 | return "debug type qualifier"; |
252 | 0 | case SPV_OPERAND_TYPE_DEBUG_OPERATION: |
253 | 0 | return "debug operation"; |
254 | 0 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS: |
255 | 0 | return "OpenCL.DebugInfo.100 debug info flags"; |
256 | 0 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING: |
257 | 0 | return "OpenCL.DebugInfo.100 debug base type encoding"; |
258 | 0 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE: |
259 | 0 | return "OpenCL.DebugInfo.100 debug composite type"; |
260 | 0 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER: |
261 | 0 | return "OpenCL.DebugInfo.100 debug type qualifier"; |
262 | 0 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION: |
263 | 0 | return "OpenCL.DebugInfo.100 debug operation"; |
264 | 0 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY: |
265 | 0 | return "OpenCL.DebugInfo.100 debug imported entity"; |
266 | | |
267 | | // The next values are for values returned from an instruction, not actually |
268 | | // an operand. So the specific strings don't matter. But let's add them |
269 | | // for completeness and ease of testing. |
270 | 0 | case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER: |
271 | 0 | return "image channel order"; |
272 | 0 | case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE: |
273 | 0 | return "image channel data type"; |
274 | | |
275 | 0 | case SPV_OPERAND_TYPE_FPDENORM_MODE: |
276 | 0 | return "FP denorm mode"; |
277 | 2 | case SPV_OPERAND_TYPE_FPOPERATION_MODE: |
278 | 2 | return "FP operation mode"; |
279 | 0 | case SPV_OPERAND_TYPE_QUANTIZATION_MODES: |
280 | 0 | return "quantization mode"; |
281 | 0 | case SPV_OPERAND_TYPE_OVERFLOW_MODES: |
282 | 0 | return "overflow mode"; |
283 | | |
284 | 0 | case SPV_OPERAND_TYPE_NONE: |
285 | 0 | return "NONE"; |
286 | 0 | default: |
287 | 0 | break; |
288 | 393 | } |
289 | 0 | return "unknown"; |
290 | 393 | } |
291 | | |
292 | | void spvPushOperandTypes(const spv_operand_type_t* types, |
293 | 1.41M | spv_operand_pattern_t* pattern) { |
294 | 1.41M | const spv_operand_type_t* endTypes; |
295 | 1.56M | for (endTypes = types; *endTypes != SPV_OPERAND_TYPE_NONE; ++endTypes) { |
296 | 155k | } |
297 | | |
298 | 1.56M | while (endTypes-- != types) { |
299 | 155k | pattern->push_back(*endTypes); |
300 | 155k | } |
301 | 1.41M | } |
302 | | |
303 | | void spvPushOperandTypesForMask(spv_target_env env, |
304 | | const spv_operand_table operandTable, |
305 | | const spv_operand_type_t type, |
306 | | const uint32_t mask, |
307 | 0 | spv_operand_pattern_t* pattern) { |
308 | | // Scan from highest bits to lowest bits because we will append in LIFO |
309 | | // fashion, and we need the operands for lower order bits to be consumed first |
310 | 0 | for (uint32_t candidate_bit = (1u << 31u); candidate_bit; |
311 | 0 | candidate_bit >>= 1) { |
312 | 0 | if (candidate_bit & mask) { |
313 | 0 | spv_operand_desc entry = nullptr; |
314 | 0 | if (SPV_SUCCESS == spvOperandTableValueLookup(env, operandTable, type, |
315 | 0 | candidate_bit, &entry)) { |
316 | 0 | spvPushOperandTypes(entry->operandTypes, pattern); |
317 | 0 | } |
318 | 0 | } |
319 | 0 | } |
320 | 0 | } |
321 | | |
322 | 18.4M | bool spvOperandIsConcrete(spv_operand_type_t type) { |
323 | 18.4M | if (spvIsIdType(type) || spvOperandIsConcreteMask(type)) { |
324 | 16.1M | return true; |
325 | 16.1M | } |
326 | 2.23M | switch (type) { |
327 | 528k | case SPV_OPERAND_TYPE_LITERAL_INTEGER: |
328 | 592k | case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: |
329 | 592k | case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: |
330 | 964k | case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER: |
331 | 1.20M | case SPV_OPERAND_TYPE_LITERAL_STRING: |
332 | 1.22M | case SPV_OPERAND_TYPE_SOURCE_LANGUAGE: |
333 | 1.27M | case SPV_OPERAND_TYPE_EXECUTION_MODEL: |
334 | 1.33M | case SPV_OPERAND_TYPE_ADDRESSING_MODEL: |
335 | 1.39M | case SPV_OPERAND_TYPE_MEMORY_MODEL: |
336 | 1.44M | case SPV_OPERAND_TYPE_EXECUTION_MODE: |
337 | 1.91M | case SPV_OPERAND_TYPE_STORAGE_CLASS: |
338 | 1.92M | case SPV_OPERAND_TYPE_DIMENSIONALITY: |
339 | 1.92M | case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE: |
340 | 1.92M | case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE: |
341 | 1.92M | case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT: |
342 | 1.92M | case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER: |
343 | 1.92M | case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE: |
344 | 1.92M | case SPV_OPERAND_TYPE_FP_ROUNDING_MODE: |
345 | 1.92M | case SPV_OPERAND_TYPE_LINKAGE_TYPE: |
346 | 1.92M | case SPV_OPERAND_TYPE_ACCESS_QUALIFIER: |
347 | 1.92M | case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE: |
348 | 2.13M | case SPV_OPERAND_TYPE_DECORATION: |
349 | 2.15M | case SPV_OPERAND_TYPE_BUILT_IN: |
350 | 2.15M | case SPV_OPERAND_TYPE_GROUP_OPERATION: |
351 | 2.15M | case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS: |
352 | 2.15M | case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO: |
353 | 2.23M | case SPV_OPERAND_TYPE_CAPABILITY: |
354 | 2.23M | case SPV_OPERAND_TYPE_RAY_FLAGS: |
355 | 2.23M | case SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION: |
356 | 2.23M | case SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE: |
357 | 2.23M | case SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE: |
358 | 2.23M | case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING: |
359 | 2.23M | case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE: |
360 | 2.23M | case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER: |
361 | 2.23M | case SPV_OPERAND_TYPE_DEBUG_OPERATION: |
362 | 2.23M | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING: |
363 | 2.23M | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE: |
364 | 2.23M | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER: |
365 | 2.23M | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION: |
366 | 2.23M | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY: |
367 | 2.23M | case SPV_OPERAND_TYPE_FPDENORM_MODE: |
368 | 2.23M | case SPV_OPERAND_TYPE_FPOPERATION_MODE: |
369 | 2.23M | case SPV_OPERAND_TYPE_QUANTIZATION_MODES: |
370 | 2.23M | case SPV_OPERAND_TYPE_OVERFLOW_MODES: |
371 | 2.23M | case SPV_OPERAND_TYPE_PACKED_VECTOR_FORMAT: |
372 | 2.23M | return true; |
373 | 0 | default: |
374 | 0 | break; |
375 | 2.23M | } |
376 | 0 | return false; |
377 | 2.23M | } |
378 | | |
379 | 5.68M | bool spvOperandIsConcreteMask(spv_operand_type_t type) { |
380 | 5.68M | switch (type) { |
381 | 895 | case SPV_OPERAND_TYPE_IMAGE: |
382 | 940 | case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE: |
383 | 133k | case SPV_OPERAND_TYPE_SELECTION_CONTROL: |
384 | 222k | case SPV_OPERAND_TYPE_LOOP_CONTROL: |
385 | 298k | case SPV_OPERAND_TYPE_FUNCTION_CONTROL: |
386 | 360k | case SPV_OPERAND_TYPE_MEMORY_ACCESS: |
387 | 360k | case SPV_OPERAND_TYPE_FRAGMENT_SHADING_RATE: |
388 | 360k | case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS: |
389 | 360k | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS: |
390 | 360k | return true; |
391 | 5.32M | default: |
392 | 5.32M | break; |
393 | 5.68M | } |
394 | 5.32M | return false; |
395 | 5.68M | } |
396 | | |
397 | 3.58M | bool spvOperandIsOptional(spv_operand_type_t type) { |
398 | 3.58M | switch (type) { |
399 | 317k | case SPV_OPERAND_TYPE_OPTIONAL_ID: |
400 | 319k | case SPV_OPERAND_TYPE_OPTIONAL_IMAGE: |
401 | 1.03M | case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS: |
402 | 1.03M | case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER: |
403 | 1.03M | case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER: |
404 | 1.03M | case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER: |
405 | 1.03M | case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING: |
406 | 1.03M | case SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER: |
407 | 1.03M | case SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT: |
408 | 1.03M | case SPV_OPERAND_TYPE_OPTIONAL_CIV: |
409 | 1.03M | return true; |
410 | 2.55M | default: |
411 | 2.55M | break; |
412 | 3.58M | } |
413 | | // Any variable operand is also optional. |
414 | 2.55M | return spvOperandIsVariable(type); |
415 | 3.58M | } |
416 | | |
417 | 2.55M | bool spvOperandIsVariable(spv_operand_type_t type) { |
418 | 2.55M | switch (type) { |
419 | 1.97M | case SPV_OPERAND_TYPE_VARIABLE_ID: |
420 | 2.24M | case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER: |
421 | 2.25M | case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID: |
422 | 2.55M | case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER: |
423 | 2.55M | return true; |
424 | 23 | default: |
425 | 23 | break; |
426 | 2.55M | } |
427 | 23 | return false; |
428 | 2.55M | } |
429 | | |
430 | | bool spvExpandOperandSequenceOnce(spv_operand_type_t type, |
431 | 21.9M | spv_operand_pattern_t* pattern) { |
432 | 21.9M | switch (type) { |
433 | 3.31M | case SPV_OPERAND_TYPE_VARIABLE_ID: |
434 | 3.31M | pattern->push_back(type); |
435 | 3.31M | pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_ID); |
436 | 3.31M | return true; |
437 | 176k | case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER: |
438 | 176k | pattern->push_back(type); |
439 | 176k | pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER); |
440 | 176k | return true; |
441 | 37.9k | case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID: |
442 | | // Represents Zero or more (Literal number, Id) pairs, |
443 | | // where the literal number must be a scalar integer. |
444 | 37.9k | pattern->push_back(type); |
445 | 37.9k | pattern->push_back(SPV_OPERAND_TYPE_ID); |
446 | 37.9k | pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER); |
447 | 37.9k | return true; |
448 | 39.8k | case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER: |
449 | | // Represents Zero or more (Id, Literal number) pairs. |
450 | 39.8k | pattern->push_back(type); |
451 | 39.8k | pattern->push_back(SPV_OPERAND_TYPE_LITERAL_INTEGER); |
452 | 39.8k | pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_ID); |
453 | 39.8k | return true; |
454 | 18.4M | default: |
455 | 18.4M | break; |
456 | 21.9M | } |
457 | 18.4M | return false; |
458 | 21.9M | } |
459 | | |
460 | | spv_operand_type_t spvTakeFirstMatchableOperand( |
461 | 18.4M | spv_operand_pattern_t* pattern) { |
462 | 18.4M | assert(!pattern->empty()); |
463 | 0 | spv_operand_type_t result; |
464 | 21.9M | do { |
465 | 21.9M | result = pattern->back(); |
466 | 21.9M | pattern->pop_back(); |
467 | 21.9M | } while (spvExpandOperandSequenceOnce(result, pattern)); |
468 | 18.4M | return result; |
469 | 18.4M | } |
470 | | |
471 | | spv_operand_pattern_t spvAlternatePatternFollowingImmediate( |
472 | 0 | const spv_operand_pattern_t& pattern) { |
473 | 0 | auto it = |
474 | 0 | std::find(pattern.crbegin(), pattern.crend(), SPV_OPERAND_TYPE_RESULT_ID); |
475 | 0 | if (it != pattern.crend()) { |
476 | 0 | spv_operand_pattern_t alternatePattern(it - pattern.crbegin() + 2, |
477 | 0 | SPV_OPERAND_TYPE_OPTIONAL_CIV); |
478 | 0 | alternatePattern[1] = SPV_OPERAND_TYPE_RESULT_ID; |
479 | 0 | return alternatePattern; |
480 | 0 | } |
481 | | |
482 | | // No result-id found, so just expect CIVs. |
483 | 0 | return {SPV_OPERAND_TYPE_OPTIONAL_CIV}; |
484 | 0 | } |
485 | | |
486 | 66.4M | bool spvIsIdType(spv_operand_type_t type) { |
487 | 66.4M | switch (type) { |
488 | 39.7M | case SPV_OPERAND_TYPE_ID: |
489 | 48.3M | case SPV_OPERAND_TYPE_TYPE_ID: |
490 | 60.0M | case SPV_OPERAND_TYPE_RESULT_ID: |
491 | 60.0M | case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID: |
492 | 60.0M | case SPV_OPERAND_TYPE_SCOPE_ID: |
493 | 60.0M | return true; |
494 | 6.42M | default: |
495 | 6.42M | return false; |
496 | 66.4M | } |
497 | 66.4M | } |
498 | | |
499 | 34.4M | bool spvIsInIdType(spv_operand_type_t type) { |
500 | 34.4M | if (!spvIsIdType(type)) { |
501 | | // If it is not an ID it cannot be an input ID. |
502 | 2.64M | return false; |
503 | 2.64M | } |
504 | 31.7M | switch (type) { |
505 | | // Deny non-input IDs. |
506 | 4.19M | case SPV_OPERAND_TYPE_TYPE_ID: |
507 | 10.0M | case SPV_OPERAND_TYPE_RESULT_ID: |
508 | 10.0M | return false; |
509 | 21.6M | default: |
510 | 21.6M | return true; |
511 | 31.7M | } |
512 | 31.7M | } |
513 | | |
514 | | std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction( |
515 | 1.37M | spv::Op opcode) { |
516 | 1.37M | std::function<bool(unsigned index)> out; |
517 | 1.37M | if (spvOpcodeGeneratesType(opcode)) { |
518 | | // All types can use forward pointers. |
519 | 93.5k | out = [](unsigned) { return true; }; |
520 | 93.5k | return out; |
521 | 93.5k | } |
522 | 1.28M | switch (opcode) { |
523 | 9.80k | case spv::Op::OpExecutionMode: |
524 | 9.80k | case spv::Op::OpExecutionModeId: |
525 | 18.6k | case spv::Op::OpEntryPoint: |
526 | 42.1k | case spv::Op::OpName: |
527 | 45.2k | case spv::Op::OpMemberName: |
528 | 66.7k | case spv::Op::OpSelectionMerge: |
529 | 103k | case spv::Op::OpDecorate: |
530 | 105k | case spv::Op::OpMemberDecorate: |
531 | 105k | case spv::Op::OpDecorateId: |
532 | 105k | case spv::Op::OpDecorateStringGOOGLE: |
533 | 105k | case spv::Op::OpMemberDecorateStringGOOGLE: |
534 | 177k | case spv::Op::OpBranch: |
535 | 192k | case spv::Op::OpLoopMerge: |
536 | 450k | out = [](unsigned) { return true; }; |
537 | 192k | break; |
538 | 280k | case spv::Op::OpGroupDecorate: |
539 | 338k | case spv::Op::OpGroupMemberDecorate: |
540 | 368k | case spv::Op::OpBranchConditional: |
541 | 372k | case spv::Op::OpSwitch: |
542 | 372k | out = [](unsigned index) { return index != 0; }; |
543 | 372k | break; |
544 | | |
545 | 8.97k | case spv::Op::OpFunctionCall: |
546 | | // The Function parameter. |
547 | 8.97k | out = [](unsigned index) { return index == 2; }; |
548 | 8.97k | break; |
549 | | |
550 | 19.4k | case spv::Op::OpPhi: |
551 | 19.4k | out = [](unsigned index) { return index > 1; }; |
552 | 19.4k | break; |
553 | | |
554 | 0 | case spv::Op::OpEnqueueKernel: |
555 | | // The Invoke parameter. |
556 | 0 | out = [](unsigned index) { return index == 8; }; |
557 | 0 | break; |
558 | | |
559 | 0 | case spv::Op::OpGetKernelNDrangeSubGroupCount: |
560 | 0 | case spv::Op::OpGetKernelNDrangeMaxSubGroupSize: |
561 | | // The Invoke parameter. |
562 | 0 | out = [](unsigned index) { return index == 3; }; |
563 | 0 | break; |
564 | | |
565 | 0 | case spv::Op::OpGetKernelWorkGroupSize: |
566 | 0 | case spv::Op::OpGetKernelPreferredWorkGroupSizeMultiple: |
567 | | // The Invoke parameter. |
568 | 0 | out = [](unsigned index) { return index == 2; }; |
569 | 0 | break; |
570 | 130 | case spv::Op::OpTypeForwardPointer: |
571 | 130 | out = [](unsigned index) { return index == 0; }; |
572 | 130 | break; |
573 | 0 | case spv::Op::OpTypeArray: |
574 | 0 | out = [](unsigned index) { return index == 1; }; |
575 | 0 | break; |
576 | 688k | default: |
577 | 688k | out = [](unsigned) { return false; }; |
578 | 688k | break; |
579 | 1.28M | } |
580 | 1.28M | return out; |
581 | 1.28M | } |
582 | | |
583 | | std::function<bool(unsigned)> spvDbgInfoExtOperandCanBeForwardDeclaredFunction( |
584 | 22 | spv_ext_inst_type_t ext_type, uint32_t key) { |
585 | | // The Vulkan debug info extended instruction set is non-semantic so allows no |
586 | | // forward references ever |
587 | 22 | if (ext_type == SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) { |
588 | 6 | return [](unsigned) { return false; }; |
589 | 6 | } |
590 | | |
591 | | // TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/532): Forward |
592 | | // references for debug info instructions are still in discussion. We must |
593 | | // update the following lines of code when we conclude the spec. |
594 | 16 | std::function<bool(unsigned index)> out; |
595 | 16 | if (ext_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) { |
596 | 0 | switch (OpenCLDebugInfo100Instructions(key)) { |
597 | 0 | case OpenCLDebugInfo100DebugFunction: |
598 | 0 | out = [](unsigned index) { return index == 13; }; |
599 | 0 | break; |
600 | 0 | case OpenCLDebugInfo100DebugTypeComposite: |
601 | 0 | out = [](unsigned index) { return index >= 13; }; |
602 | 0 | break; |
603 | 0 | default: |
604 | 0 | out = [](unsigned) { return false; }; |
605 | 0 | break; |
606 | 0 | } |
607 | 16 | } else { |
608 | 16 | switch (DebugInfoInstructions(key)) { |
609 | 1 | case DebugInfoDebugFunction: |
610 | 1 | out = [](unsigned index) { return index == 13; }; |
611 | 1 | break; |
612 | 2 | case DebugInfoDebugTypeComposite: |
613 | 2 | out = [](unsigned index) { return index >= 12; }; |
614 | 2 | break; |
615 | 13 | default: |
616 | 13 | out = [](unsigned) { return false; }; |
617 | 13 | break; |
618 | 16 | } |
619 | 16 | } |
620 | 16 | return out; |
621 | 16 | } |