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/spirv_constant.h" |
28 | #include "source/spirv_target_env.h" |
29 | |
30 | // For now, assume unified1 contains up to SPIR-V 1.3 and no later |
31 | // SPIR-V version. |
32 | // TODO(dneto): Make one set of tables, but with version tags on a |
33 | // per-item basis. https://github.com/KhronosGroup/SPIRV-Tools/issues/1195 |
34 | |
35 | #include "operand.kinds-unified1.inc" |
36 | #include "spirv-tools/libspirv.h" |
37 | |
38 | static const spv_operand_table_t kOperandTable = { |
39 | ARRAY_SIZE(pygen_variable_OperandInfoTable), |
40 | pygen_variable_OperandInfoTable}; |
41 | |
42 | spv_result_t spvOperandTableGet(spv_operand_table* pOperandTable, |
43 | spv_target_env) { |
44 | if (!pOperandTable) return SPV_ERROR_INVALID_POINTER; |
45 | |
46 | *pOperandTable = &kOperandTable; |
47 | return SPV_SUCCESS; |
48 | } |
49 | |
50 | spv_result_t spvOperandTableNameLookup(spv_target_env env, |
51 | const spv_operand_table table, |
52 | const spv_operand_type_t type, |
53 | const char* name, |
54 | const size_t nameLength, |
55 | spv_operand_desc* pEntry) { |
56 | if (!table) return SPV_ERROR_INVALID_TABLE; |
57 | if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER; |
58 | |
59 | const auto version = spvVersionForTargetEnv(env); |
60 | for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) { |
61 | const auto& group = table->types[typeIndex]; |
62 | if (type != group.type) continue; |
63 | for (uint64_t index = 0; index < group.count; ++index) { |
64 | const auto& entry = group.entries[index]; |
65 | // We consider the current operand as available as long as |
66 | // 1. The target environment satisfies the minimal requirement of the |
67 | // operand; or |
68 | // 2. There is at least one extension enabling this operand; or |
69 | // 3. There is at least one capability enabling this operand. |
70 | // |
71 | // Note that the second rule assumes the extension enabling this operand |
72 | // is indeed requested in the SPIR-V code; checking that should be |
73 | // validator's work. |
74 | if (((version >= entry.minVersion && version <= entry.lastVersion) || |
75 | entry.numExtensions > 0u || entry.numCapabilities > 0u) && |
76 | nameLength == strlen(entry.name) && |
77 | !strncmp(entry.name, name, nameLength)) { |
78 | *pEntry = &entry; |
79 | return SPV_SUCCESS; |
80 | } |
81 | } |
82 | } |
83 | |
84 | return SPV_ERROR_INVALID_LOOKUP; |
85 | } |
86 | |
87 | spv_result_t spvOperandTableValueLookup(spv_target_env env, |
88 | const spv_operand_table table, |
89 | const spv_operand_type_t type, |
90 | const uint32_t value, |
91 | spv_operand_desc* pEntry) { |
92 | if (!table) return SPV_ERROR_INVALID_TABLE; |
93 | if (!pEntry) return SPV_ERROR_INVALID_POINTER; |
94 | |
95 | spv_operand_desc_t needle = {"" , value, 0, nullptr, 0, nullptr, {}, ~0u, ~0u}; |
96 | |
97 | auto comp = [](const spv_operand_desc_t& lhs, const spv_operand_desc_t& rhs) { |
98 | return lhs.value < rhs.value; |
99 | }; |
100 | |
101 | for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) { |
102 | const auto& group = table->types[typeIndex]; |
103 | if (type != group.type) continue; |
104 | |
105 | const auto beg = group.entries; |
106 | const auto end = group.entries + group.count; |
107 | |
108 | // We need to loop here because there can exist multiple symbols for the |
109 | // same operand value, and they can be introduced in different target |
110 | // environments, which means they can have different minimal version |
111 | // requirements. For example, SubgroupEqMaskKHR can exist in any SPIR-V |
112 | // version as long as the SPV_KHR_shader_ballot extension is there; but |
113 | // starting from SPIR-V 1.3, SubgroupEqMask, which has the same numeric |
114 | // value as SubgroupEqMaskKHR, is available in core SPIR-V without extension |
115 | // requirements. |
116 | // Assumes the underlying table is already sorted ascendingly according to |
117 | // opcode value. |
118 | const auto version = spvVersionForTargetEnv(env); |
119 | for (auto it = std::lower_bound(beg, end, needle, comp); |
120 | it != end && it->value == value; ++it) { |
121 | // We consider the current operand as available as long as |
122 | // 1. The target environment satisfies the minimal requirement of the |
123 | // operand; or |
124 | // 2. There is at least one extension enabling this operand; or |
125 | // 3. There is at least one capability enabling this operand. |
126 | // |
127 | // Note that the second rule assumes the extension enabling this operand |
128 | // is indeed requested in the SPIR-V code; checking that should be |
129 | // validator's work. |
130 | if ((version >= it->minVersion && version <= it->lastVersion) || |
131 | it->numExtensions > 0u || it->numCapabilities > 0u) { |
132 | *pEntry = it; |
133 | return SPV_SUCCESS; |
134 | } |
135 | } |
136 | } |
137 | |
138 | return SPV_ERROR_INVALID_LOOKUP; |
139 | } |
140 | |
141 | const char* spvOperandTypeStr(spv_operand_type_t type) { |
142 | switch (type) { |
143 | case SPV_OPERAND_TYPE_ID: |
144 | case SPV_OPERAND_TYPE_OPTIONAL_ID: |
145 | return "ID" ; |
146 | case SPV_OPERAND_TYPE_TYPE_ID: |
147 | return "type ID" ; |
148 | case SPV_OPERAND_TYPE_RESULT_ID: |
149 | return "result ID" ; |
150 | case SPV_OPERAND_TYPE_LITERAL_INTEGER: |
151 | case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER: |
152 | case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER: |
153 | return "literal number" ; |
154 | case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER: |
155 | return "possibly multi-word literal integer" ; |
156 | case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER: |
157 | return "possibly multi-word literal number" ; |
158 | case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: |
159 | return "extension instruction number" ; |
160 | case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: |
161 | return "OpSpecConstantOp opcode" ; |
162 | case SPV_OPERAND_TYPE_LITERAL_STRING: |
163 | case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING: |
164 | return "literal string" ; |
165 | case SPV_OPERAND_TYPE_SOURCE_LANGUAGE: |
166 | return "source language" ; |
167 | case SPV_OPERAND_TYPE_EXECUTION_MODEL: |
168 | return "execution model" ; |
169 | case SPV_OPERAND_TYPE_ADDRESSING_MODEL: |
170 | return "addressing model" ; |
171 | case SPV_OPERAND_TYPE_MEMORY_MODEL: |
172 | return "memory model" ; |
173 | case SPV_OPERAND_TYPE_EXECUTION_MODE: |
174 | return "execution mode" ; |
175 | case SPV_OPERAND_TYPE_STORAGE_CLASS: |
176 | return "storage class" ; |
177 | case SPV_OPERAND_TYPE_DIMENSIONALITY: |
178 | return "dimensionality" ; |
179 | case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE: |
180 | return "sampler addressing mode" ; |
181 | case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE: |
182 | return "sampler filter mode" ; |
183 | case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT: |
184 | return "image format" ; |
185 | case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE: |
186 | return "floating-point fast math mode" ; |
187 | case SPV_OPERAND_TYPE_FP_ROUNDING_MODE: |
188 | return "floating-point rounding mode" ; |
189 | case SPV_OPERAND_TYPE_LINKAGE_TYPE: |
190 | return "linkage type" ; |
191 | case SPV_OPERAND_TYPE_ACCESS_QUALIFIER: |
192 | case SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER: |
193 | return "access qualifier" ; |
194 | case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE: |
195 | return "function parameter attribute" ; |
196 | case SPV_OPERAND_TYPE_DECORATION: |
197 | return "decoration" ; |
198 | case SPV_OPERAND_TYPE_BUILT_IN: |
199 | return "built-in" ; |
200 | case SPV_OPERAND_TYPE_SELECTION_CONTROL: |
201 | return "selection control" ; |
202 | case SPV_OPERAND_TYPE_LOOP_CONTROL: |
203 | return "loop control" ; |
204 | case SPV_OPERAND_TYPE_FUNCTION_CONTROL: |
205 | return "function control" ; |
206 | case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID: |
207 | return "memory semantics ID" ; |
208 | case SPV_OPERAND_TYPE_MEMORY_ACCESS: |
209 | case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS: |
210 | return "memory access" ; |
211 | case SPV_OPERAND_TYPE_SCOPE_ID: |
212 | return "scope ID" ; |
213 | case SPV_OPERAND_TYPE_GROUP_OPERATION: |
214 | return "group operation" ; |
215 | case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS: |
216 | return "kernel enqeue flags" ; |
217 | case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO: |
218 | return "kernel profiling info" ; |
219 | case SPV_OPERAND_TYPE_CAPABILITY: |
220 | return "capability" ; |
221 | case SPV_OPERAND_TYPE_RAY_FLAGS: |
222 | return "ray flags" ; |
223 | case SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION: |
224 | return "ray query intersection" ; |
225 | case SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE: |
226 | return "ray query committed intersection type" ; |
227 | case SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE: |
228 | return "ray query candidate intersection type" ; |
229 | case SPV_OPERAND_TYPE_IMAGE: |
230 | case SPV_OPERAND_TYPE_OPTIONAL_IMAGE: |
231 | return "image" ; |
232 | case SPV_OPERAND_TYPE_OPTIONAL_CIV: |
233 | return "context-insensitive value" ; |
234 | case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS: |
235 | return "debug info flags" ; |
236 | case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING: |
237 | return "debug base type encoding" ; |
238 | case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE: |
239 | return "debug composite type" ; |
240 | case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER: |
241 | return "debug type qualifier" ; |
242 | case SPV_OPERAND_TYPE_DEBUG_OPERATION: |
243 | return "debug operation" ; |
244 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS: |
245 | return "OpenCL.DebugInfo.100 debug info flags" ; |
246 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING: |
247 | return "OpenCL.DebugInfo.100 debug base type encoding" ; |
248 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE: |
249 | return "OpenCL.DebugInfo.100 debug composite type" ; |
250 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER: |
251 | return "OpenCL.DebugInfo.100 debug type qualifier" ; |
252 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION: |
253 | return "OpenCL.DebugInfo.100 debug operation" ; |
254 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY: |
255 | return "OpenCL.DebugInfo.100 debug imported entity" ; |
256 | |
257 | // The next values are for values returned from an instruction, not actually |
258 | // an operand. So the specific strings don't matter. But let's add them |
259 | // for completeness and ease of testing. |
260 | case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER: |
261 | return "image channel order" ; |
262 | case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE: |
263 | return "image channel data type" ; |
264 | |
265 | case SPV_OPERAND_TYPE_NONE: |
266 | return "NONE" ; |
267 | default: |
268 | assert(0 && "Unhandled operand type!" ); |
269 | break; |
270 | } |
271 | return "unknown" ; |
272 | } |
273 | |
274 | void spvPushOperandTypes(const spv_operand_type_t* types, |
275 | spv_operand_pattern_t* pattern) { |
276 | const spv_operand_type_t* endTypes; |
277 | for (endTypes = types; *endTypes != SPV_OPERAND_TYPE_NONE; ++endTypes) { |
278 | } |
279 | |
280 | while (endTypes-- != types) { |
281 | pattern->push_back(*endTypes); |
282 | } |
283 | } |
284 | |
285 | void spvPushOperandTypesForMask(spv_target_env env, |
286 | const spv_operand_table operandTable, |
287 | const spv_operand_type_t type, |
288 | const uint32_t mask, |
289 | spv_operand_pattern_t* pattern) { |
290 | // Scan from highest bits to lowest bits because we will append in LIFO |
291 | // fashion, and we need the operands for lower order bits to be consumed first |
292 | for (uint32_t candidate_bit = (1u << 31u); candidate_bit; |
293 | candidate_bit >>= 1) { |
294 | if (candidate_bit & mask) { |
295 | spv_operand_desc entry = nullptr; |
296 | if (SPV_SUCCESS == spvOperandTableValueLookup(env, operandTable, type, |
297 | candidate_bit, &entry)) { |
298 | spvPushOperandTypes(entry->operandTypes, pattern); |
299 | } |
300 | } |
301 | } |
302 | } |
303 | |
304 | bool spvOperandIsConcrete(spv_operand_type_t type) { |
305 | if (spvIsIdType(type) || spvOperandIsConcreteMask(type)) { |
306 | return true; |
307 | } |
308 | switch (type) { |
309 | case SPV_OPERAND_TYPE_LITERAL_INTEGER: |
310 | case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: |
311 | case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: |
312 | case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER: |
313 | case SPV_OPERAND_TYPE_LITERAL_STRING: |
314 | case SPV_OPERAND_TYPE_SOURCE_LANGUAGE: |
315 | case SPV_OPERAND_TYPE_EXECUTION_MODEL: |
316 | case SPV_OPERAND_TYPE_ADDRESSING_MODEL: |
317 | case SPV_OPERAND_TYPE_MEMORY_MODEL: |
318 | case SPV_OPERAND_TYPE_EXECUTION_MODE: |
319 | case SPV_OPERAND_TYPE_STORAGE_CLASS: |
320 | case SPV_OPERAND_TYPE_DIMENSIONALITY: |
321 | case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE: |
322 | case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE: |
323 | case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT: |
324 | case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER: |
325 | case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE: |
326 | case SPV_OPERAND_TYPE_FP_ROUNDING_MODE: |
327 | case SPV_OPERAND_TYPE_LINKAGE_TYPE: |
328 | case SPV_OPERAND_TYPE_ACCESS_QUALIFIER: |
329 | case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE: |
330 | case SPV_OPERAND_TYPE_DECORATION: |
331 | case SPV_OPERAND_TYPE_BUILT_IN: |
332 | case SPV_OPERAND_TYPE_GROUP_OPERATION: |
333 | case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS: |
334 | case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO: |
335 | case SPV_OPERAND_TYPE_CAPABILITY: |
336 | case SPV_OPERAND_TYPE_RAY_FLAGS: |
337 | case SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION: |
338 | case SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE: |
339 | case SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE: |
340 | case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING: |
341 | case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE: |
342 | case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER: |
343 | case SPV_OPERAND_TYPE_DEBUG_OPERATION: |
344 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING: |
345 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE: |
346 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER: |
347 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION: |
348 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY: |
349 | return true; |
350 | default: |
351 | break; |
352 | } |
353 | return false; |
354 | } |
355 | |
356 | bool spvOperandIsConcreteMask(spv_operand_type_t type) { |
357 | switch (type) { |
358 | case SPV_OPERAND_TYPE_IMAGE: |
359 | case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE: |
360 | case SPV_OPERAND_TYPE_SELECTION_CONTROL: |
361 | case SPV_OPERAND_TYPE_LOOP_CONTROL: |
362 | case SPV_OPERAND_TYPE_FUNCTION_CONTROL: |
363 | case SPV_OPERAND_TYPE_MEMORY_ACCESS: |
364 | case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS: |
365 | case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS: |
366 | return true; |
367 | default: |
368 | break; |
369 | } |
370 | return false; |
371 | } |
372 | |
373 | bool spvOperandIsOptional(spv_operand_type_t type) { |
374 | return SPV_OPERAND_TYPE_FIRST_OPTIONAL_TYPE <= type && |
375 | type <= SPV_OPERAND_TYPE_LAST_OPTIONAL_TYPE; |
376 | } |
377 | |
378 | bool spvOperandIsVariable(spv_operand_type_t type) { |
379 | return SPV_OPERAND_TYPE_FIRST_VARIABLE_TYPE <= type && |
380 | type <= SPV_OPERAND_TYPE_LAST_VARIABLE_TYPE; |
381 | } |
382 | |
383 | bool spvExpandOperandSequenceOnce(spv_operand_type_t type, |
384 | spv_operand_pattern_t* pattern) { |
385 | switch (type) { |
386 | case SPV_OPERAND_TYPE_VARIABLE_ID: |
387 | pattern->push_back(type); |
388 | pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_ID); |
389 | return true; |
390 | case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER: |
391 | pattern->push_back(type); |
392 | pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER); |
393 | return true; |
394 | case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID: |
395 | // Represents Zero or more (Literal number, Id) pairs, |
396 | // where the literal number must be a scalar integer. |
397 | pattern->push_back(type); |
398 | pattern->push_back(SPV_OPERAND_TYPE_ID); |
399 | pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER); |
400 | return true; |
401 | case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER: |
402 | // Represents Zero or more (Id, Literal number) pairs. |
403 | pattern->push_back(type); |
404 | pattern->push_back(SPV_OPERAND_TYPE_LITERAL_INTEGER); |
405 | pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_ID); |
406 | return true; |
407 | default: |
408 | break; |
409 | } |
410 | return false; |
411 | } |
412 | |
413 | spv_operand_type_t spvTakeFirstMatchableOperand( |
414 | spv_operand_pattern_t* pattern) { |
415 | assert(!pattern->empty()); |
416 | spv_operand_type_t result; |
417 | do { |
418 | result = pattern->back(); |
419 | pattern->pop_back(); |
420 | } while (spvExpandOperandSequenceOnce(result, pattern)); |
421 | return result; |
422 | } |
423 | |
424 | spv_operand_pattern_t spvAlternatePatternFollowingImmediate( |
425 | const spv_operand_pattern_t& pattern) { |
426 | auto it = |
427 | std::find(pattern.crbegin(), pattern.crend(), SPV_OPERAND_TYPE_RESULT_ID); |
428 | if (it != pattern.crend()) { |
429 | spv_operand_pattern_t alternatePattern(it - pattern.crbegin() + 2, |
430 | SPV_OPERAND_TYPE_OPTIONAL_CIV); |
431 | alternatePattern[1] = SPV_OPERAND_TYPE_RESULT_ID; |
432 | return alternatePattern; |
433 | } |
434 | |
435 | // No result-id found, so just expect CIVs. |
436 | return {SPV_OPERAND_TYPE_OPTIONAL_CIV}; |
437 | } |
438 | |
439 | bool spvIsIdType(spv_operand_type_t type) { |
440 | switch (type) { |
441 | case SPV_OPERAND_TYPE_ID: |
442 | case SPV_OPERAND_TYPE_TYPE_ID: |
443 | case SPV_OPERAND_TYPE_RESULT_ID: |
444 | case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID: |
445 | case SPV_OPERAND_TYPE_SCOPE_ID: |
446 | return true; |
447 | default: |
448 | return false; |
449 | } |
450 | } |
451 | |
452 | bool spvIsInIdType(spv_operand_type_t type) { |
453 | if (!spvIsIdType(type)) { |
454 | // If it is not an ID it cannot be an input ID. |
455 | return false; |
456 | } |
457 | switch (type) { |
458 | // Blacklist non-input IDs. |
459 | case SPV_OPERAND_TYPE_TYPE_ID: |
460 | case SPV_OPERAND_TYPE_RESULT_ID: |
461 | return false; |
462 | default: |
463 | return true; |
464 | } |
465 | } |
466 | |
467 | std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction( |
468 | SpvOp opcode) { |
469 | std::function<bool(unsigned index)> out; |
470 | switch (opcode) { |
471 | case SpvOpExecutionMode: |
472 | case SpvOpExecutionModeId: |
473 | case SpvOpEntryPoint: |
474 | case SpvOpName: |
475 | case SpvOpMemberName: |
476 | case SpvOpSelectionMerge: |
477 | case SpvOpDecorate: |
478 | case SpvOpMemberDecorate: |
479 | case SpvOpDecorateId: |
480 | case SpvOpDecorateStringGOOGLE: |
481 | case SpvOpMemberDecorateStringGOOGLE: |
482 | case SpvOpTypeStruct: |
483 | case SpvOpBranch: |
484 | case SpvOpLoopMerge: |
485 | out = [](unsigned) { return true; }; |
486 | break; |
487 | case SpvOpGroupDecorate: |
488 | case SpvOpGroupMemberDecorate: |
489 | case SpvOpBranchConditional: |
490 | case SpvOpSwitch: |
491 | out = [](unsigned index) { return index != 0; }; |
492 | break; |
493 | |
494 | case SpvOpFunctionCall: |
495 | // The Function parameter. |
496 | out = [](unsigned index) { return index == 2; }; |
497 | break; |
498 | |
499 | case SpvOpPhi: |
500 | out = [](unsigned index) { return index > 1; }; |
501 | break; |
502 | |
503 | case SpvOpEnqueueKernel: |
504 | // The Invoke parameter. |
505 | out = [](unsigned index) { return index == 8; }; |
506 | break; |
507 | |
508 | case SpvOpGetKernelNDrangeSubGroupCount: |
509 | case SpvOpGetKernelNDrangeMaxSubGroupSize: |
510 | // The Invoke parameter. |
511 | out = [](unsigned index) { return index == 3; }; |
512 | break; |
513 | |
514 | case SpvOpGetKernelWorkGroupSize: |
515 | case SpvOpGetKernelPreferredWorkGroupSizeMultiple: |
516 | // The Invoke parameter. |
517 | out = [](unsigned index) { return index == 2; }; |
518 | break; |
519 | case SpvOpTypeForwardPointer: |
520 | out = [](unsigned index) { return index == 0; }; |
521 | break; |
522 | case SpvOpTypeArray: |
523 | out = [](unsigned index) { return index == 1; }; |
524 | break; |
525 | default: |
526 | out = [](unsigned) { return false; }; |
527 | break; |
528 | } |
529 | return out; |
530 | } |
531 | |
532 | std::function<bool(unsigned)> spvDbgInfoExtOperandCanBeForwardDeclaredFunction( |
533 | spv_ext_inst_type_t ext_type, uint32_t key) { |
534 | // TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/532): Forward |
535 | // references for debug info instructions are still in discussion. We must |
536 | // update the following lines of code when we conclude the spec. |
537 | std::function<bool(unsigned index)> out; |
538 | if (ext_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) { |
539 | switch (OpenCLDebugInfo100Instructions(key)) { |
540 | case OpenCLDebugInfo100DebugFunction: |
541 | out = [](unsigned index) { return index == 13; }; |
542 | break; |
543 | case OpenCLDebugInfo100DebugTypeComposite: |
544 | out = [](unsigned index) { return index >= 13; }; |
545 | break; |
546 | default: |
547 | out = [](unsigned) { return false; }; |
548 | break; |
549 | } |
550 | } else { |
551 | switch (DebugInfoInstructions(key)) { |
552 | case DebugInfoDebugFunction: |
553 | out = [](unsigned index) { return index == 13; }; |
554 | break; |
555 | case DebugInfoDebugTypeComposite: |
556 | out = [](unsigned index) { return index >= 12; }; |
557 | break; |
558 | default: |
559 | out = [](unsigned) { return false; }; |
560 | break; |
561 | } |
562 | } |
563 | return out; |
564 | } |
565 | |