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
39static const spv_operand_table_t kOperandTable = {
40 ARRAY_SIZE(pygen_variable_OperandInfoTable),
41 pygen_variable_OperandInfoTable};
42
43spv_result_t spvOperandTableGet(spv_operand_table* pOperandTable,
44 spv_target_env) {
45 if (!pOperandTable) return SPV_ERROR_INVALID_POINTER;
46
47 *pOperandTable = &kOperandTable;
48 return SPV_SUCCESS;
49}
50
51spv_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 spv_operand_desc* pEntry) {
57 if (!table) return SPV_ERROR_INVALID_TABLE;
58 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
59
60 const auto version = spvVersionForTargetEnv(env);
61 for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
62 const auto& group = table->types[typeIndex];
63 if (type != group.type) continue;
64 for (uint64_t index = 0; index < group.count; ++index) {
65 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 if (nameLength == strlen(entry.name) &&
76 !strncmp(entry.name, name, nameLength)) {
77 if ((version >= entry.minVersion && version <= entry.lastVersion) ||
78 entry.numExtensions > 0u || entry.numCapabilities > 0u) {
79 *pEntry = &entry;
80 return SPV_SUCCESS;
81 } else {
82 // if there is no extension/capability then the version is wrong
83 return SPV_ERROR_WRONG_VERSION;
84 }
85 }
86 }
87 }
88
89 return SPV_ERROR_INVALID_LOOKUP;
90}
91
92spv_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 spv_operand_desc* pEntry) {
97 if (!table) return SPV_ERROR_INVALID_TABLE;
98 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
99
100 spv_operand_desc_t needle = {"", value, 0, nullptr, 0, nullptr, {}, ~0u, ~0u};
101
102 auto comp = [](const spv_operand_desc_t& lhs, const spv_operand_desc_t& rhs) {
103 return lhs.value < rhs.value;
104 };
105
106 for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
107 const auto& group = table->types[typeIndex];
108 if (type != group.type) continue;
109
110 const auto beg = group.entries;
111 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 const auto version = spvVersionForTargetEnv(env);
124 for (auto it = std::lower_bound(beg, end, needle, comp);
125 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 if ((version >= it->minVersion && version <= it->lastVersion) ||
136 it->numExtensions > 0u || it->numCapabilities > 0u) {
137 *pEntry = it;
138 return SPV_SUCCESS;
139 }
140 }
141 }
142
143 return SPV_ERROR_INVALID_LOOKUP;
144}
145
146const char* spvOperandTypeStr(spv_operand_type_t type) {
147 switch (type) {
148 case SPV_OPERAND_TYPE_ID:
149 case SPV_OPERAND_TYPE_OPTIONAL_ID:
150 return "ID";
151 case SPV_OPERAND_TYPE_TYPE_ID:
152 return "type ID";
153 case SPV_OPERAND_TYPE_RESULT_ID:
154 return "result ID";
155 case SPV_OPERAND_TYPE_LITERAL_INTEGER:
156 case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER:
157 case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER:
158 return "literal number";
159 case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
160 return "possibly multi-word literal integer";
161 case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
162 return "possibly multi-word literal number";
163 case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER:
164 return "extension instruction number";
165 case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER:
166 return "OpSpecConstantOp opcode";
167 case SPV_OPERAND_TYPE_LITERAL_STRING:
168 case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING:
169 return "literal string";
170 case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
171 return "source language";
172 case SPV_OPERAND_TYPE_EXECUTION_MODEL:
173 return "execution model";
174 case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
175 return "addressing model";
176 case SPV_OPERAND_TYPE_MEMORY_MODEL:
177 return "memory model";
178 case SPV_OPERAND_TYPE_EXECUTION_MODE:
179 return "execution mode";
180 case SPV_OPERAND_TYPE_STORAGE_CLASS:
181 return "storage class";
182 case SPV_OPERAND_TYPE_DIMENSIONALITY:
183 return "dimensionality";
184 case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
185 return "sampler addressing mode";
186 case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
187 return "sampler filter mode";
188 case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT:
189 return "image format";
190 case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
191 return "floating-point fast math mode";
192 case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
193 return "floating-point rounding mode";
194 case SPV_OPERAND_TYPE_LINKAGE_TYPE:
195 return "linkage type";
196 case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
197 case SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER:
198 return "access qualifier";
199 case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
200 return "function parameter attribute";
201 case SPV_OPERAND_TYPE_DECORATION:
202 return "decoration";
203 case SPV_OPERAND_TYPE_BUILT_IN:
204 return "built-in";
205 case SPV_OPERAND_TYPE_SELECTION_CONTROL:
206 return "selection control";
207 case SPV_OPERAND_TYPE_LOOP_CONTROL:
208 return "loop control";
209 case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
210 return "function control";
211 case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
212 return "memory semantics ID";
213 case SPV_OPERAND_TYPE_MEMORY_ACCESS:
214 case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
215 return "memory access";
216 case SPV_OPERAND_TYPE_FRAGMENT_SHADING_RATE:
217 return "shading rate";
218 case SPV_OPERAND_TYPE_SCOPE_ID:
219 return "scope ID";
220 case SPV_OPERAND_TYPE_GROUP_OPERATION:
221 return "group operation";
222 case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
223 return "kernel enqeue flags";
224 case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
225 return "kernel profiling info";
226 case SPV_OPERAND_TYPE_CAPABILITY:
227 return "capability";
228 case SPV_OPERAND_TYPE_RAY_FLAGS:
229 return "ray flags";
230 case SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION:
231 return "ray query intersection";
232 case SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE:
233 return "ray query committed intersection type";
234 case SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE:
235 return "ray query candidate intersection type";
236 case SPV_OPERAND_TYPE_PACKED_VECTOR_FORMAT:
237 case SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT:
238 return "packed vector format";
239 case SPV_OPERAND_TYPE_IMAGE:
240 case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
241 return "image";
242 case SPV_OPERAND_TYPE_OPTIONAL_CIV:
243 return "context-insensitive value";
244 case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
245 return "debug info flags";
246 case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
247 return "debug base type encoding";
248 case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE:
249 return "debug composite type";
250 case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER:
251 return "debug type qualifier";
252 case SPV_OPERAND_TYPE_DEBUG_OPERATION:
253 return "debug operation";
254 case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS:
255 return "OpenCL.DebugInfo.100 debug info flags";
256 case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
257 return "OpenCL.DebugInfo.100 debug base type encoding";
258 case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE:
259 return "OpenCL.DebugInfo.100 debug composite type";
260 case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER:
261 return "OpenCL.DebugInfo.100 debug type qualifier";
262 case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION:
263 return "OpenCL.DebugInfo.100 debug operation";
264 case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY:
265 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 case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER:
271 return "image channel order";
272 case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE:
273 return "image channel data type";
274
275 case SPV_OPERAND_TYPE_FPDENORM_MODE:
276 return "FP denorm mode";
277 case SPV_OPERAND_TYPE_FPOPERATION_MODE:
278 return "FP operation mode";
279 case SPV_OPERAND_TYPE_QUANTIZATION_MODES:
280 return "quantization mode";
281 case SPV_OPERAND_TYPE_OVERFLOW_MODES:
282 return "overflow mode";
283
284 case SPV_OPERAND_TYPE_NONE:
285 return "NONE";
286 default:
287 break;
288 }
289 return "unknown";
290}
291
292void spvPushOperandTypes(const spv_operand_type_t* types,
293 spv_operand_pattern_t* pattern) {
294 const spv_operand_type_t* endTypes;
295 for (endTypes = types; *endTypes != SPV_OPERAND_TYPE_NONE; ++endTypes) {
296 }
297
298 while (endTypes-- != types) {
299 pattern->push_back(*endTypes);
300 }
301}
302
303void spvPushOperandTypesForMask(spv_target_env env,
304 const spv_operand_table operandTable,
305 const spv_operand_type_t type,
306 const uint32_t mask,
307 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 for (uint32_t candidate_bit = (1u << 31u); candidate_bit;
311 candidate_bit >>= 1) {
312 if (candidate_bit & mask) {
313 spv_operand_desc entry = nullptr;
314 if (SPV_SUCCESS == spvOperandTableValueLookup(env, operandTable, type,
315 candidate_bit, &entry)) {
316 spvPushOperandTypes(entry->operandTypes, pattern);
317 }
318 }
319 }
320}
321
322bool spvOperandIsConcrete(spv_operand_type_t type) {
323 if (spvIsIdType(type) || spvOperandIsConcreteMask(type)) {
324 return true;
325 }
326 switch (type) {
327 case SPV_OPERAND_TYPE_LITERAL_INTEGER:
328 case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER:
329 case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER:
330 case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
331 case SPV_OPERAND_TYPE_LITERAL_STRING:
332 case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
333 case SPV_OPERAND_TYPE_EXECUTION_MODEL:
334 case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
335 case SPV_OPERAND_TYPE_MEMORY_MODEL:
336 case SPV_OPERAND_TYPE_EXECUTION_MODE:
337 case SPV_OPERAND_TYPE_STORAGE_CLASS:
338 case SPV_OPERAND_TYPE_DIMENSIONALITY:
339 case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
340 case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
341 case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT:
342 case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER:
343 case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE:
344 case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
345 case SPV_OPERAND_TYPE_LINKAGE_TYPE:
346 case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
347 case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
348 case SPV_OPERAND_TYPE_DECORATION:
349 case SPV_OPERAND_TYPE_BUILT_IN:
350 case SPV_OPERAND_TYPE_GROUP_OPERATION:
351 case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
352 case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
353 case SPV_OPERAND_TYPE_CAPABILITY:
354 case SPV_OPERAND_TYPE_RAY_FLAGS:
355 case SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION:
356 case SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE:
357 case SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE:
358 case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
359 case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE:
360 case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER:
361 case SPV_OPERAND_TYPE_DEBUG_OPERATION:
362 case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
363 case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE:
364 case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER:
365 case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION:
366 case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY:
367 case SPV_OPERAND_TYPE_FPDENORM_MODE:
368 case SPV_OPERAND_TYPE_FPOPERATION_MODE:
369 case SPV_OPERAND_TYPE_QUANTIZATION_MODES:
370 case SPV_OPERAND_TYPE_OVERFLOW_MODES:
371 case SPV_OPERAND_TYPE_PACKED_VECTOR_FORMAT:
372 return true;
373 default:
374 break;
375 }
376 return false;
377}
378
379bool spvOperandIsConcreteMask(spv_operand_type_t type) {
380 switch (type) {
381 case SPV_OPERAND_TYPE_IMAGE:
382 case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
383 case SPV_OPERAND_TYPE_SELECTION_CONTROL:
384 case SPV_OPERAND_TYPE_LOOP_CONTROL:
385 case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
386 case SPV_OPERAND_TYPE_MEMORY_ACCESS:
387 case SPV_OPERAND_TYPE_FRAGMENT_SHADING_RATE:
388 case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
389 case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS:
390 return true;
391 default:
392 break;
393 }
394 return false;
395}
396
397bool spvOperandIsOptional(spv_operand_type_t type) {
398 switch (type) {
399 case SPV_OPERAND_TYPE_OPTIONAL_ID:
400 case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
401 case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
402 case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER:
403 case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER:
404 case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
405 case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING:
406 case SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER:
407 case SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT:
408 case SPV_OPERAND_TYPE_OPTIONAL_CIV:
409 return true;
410 default:
411 break;
412 }
413 // Any variable operand is also optional.
414 return spvOperandIsVariable(type);
415}
416
417bool spvOperandIsVariable(spv_operand_type_t type) {
418 switch (type) {
419 case SPV_OPERAND_TYPE_VARIABLE_ID:
420 case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER:
421 case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID:
422 case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER:
423 return true;
424 default:
425 break;
426 }
427 return false;
428}
429
430bool spvExpandOperandSequenceOnce(spv_operand_type_t type,
431 spv_operand_pattern_t* pattern) {
432 switch (type) {
433 case SPV_OPERAND_TYPE_VARIABLE_ID:
434 pattern->push_back(type);
435 pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_ID);
436 return true;
437 case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER:
438 pattern->push_back(type);
439 pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER);
440 return true;
441 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 pattern->push_back(type);
445 pattern->push_back(SPV_OPERAND_TYPE_ID);
446 pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER);
447 return true;
448 case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER:
449 // Represents Zero or more (Id, Literal number) pairs.
450 pattern->push_back(type);
451 pattern->push_back(SPV_OPERAND_TYPE_LITERAL_INTEGER);
452 pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_ID);
453 return true;
454 default:
455 break;
456 }
457 return false;
458}
459
460spv_operand_type_t spvTakeFirstMatchableOperand(
461 spv_operand_pattern_t* pattern) {
462 assert(!pattern->empty());
463 spv_operand_type_t result;
464 do {
465 result = pattern->back();
466 pattern->pop_back();
467 } while (spvExpandOperandSequenceOnce(result, pattern));
468 return result;
469}
470
471spv_operand_pattern_t spvAlternatePatternFollowingImmediate(
472 const spv_operand_pattern_t& pattern) {
473 auto it =
474 std::find(pattern.crbegin(), pattern.crend(), SPV_OPERAND_TYPE_RESULT_ID);
475 if (it != pattern.crend()) {
476 spv_operand_pattern_t alternatePattern(it - pattern.crbegin() + 2,
477 SPV_OPERAND_TYPE_OPTIONAL_CIV);
478 alternatePattern[1] = SPV_OPERAND_TYPE_RESULT_ID;
479 return alternatePattern;
480 }
481
482 // No result-id found, so just expect CIVs.
483 return {SPV_OPERAND_TYPE_OPTIONAL_CIV};
484}
485
486bool spvIsIdType(spv_operand_type_t type) {
487 switch (type) {
488 case SPV_OPERAND_TYPE_ID:
489 case SPV_OPERAND_TYPE_TYPE_ID:
490 case SPV_OPERAND_TYPE_RESULT_ID:
491 case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
492 case SPV_OPERAND_TYPE_SCOPE_ID:
493 return true;
494 default:
495 return false;
496 }
497}
498
499bool spvIsInIdType(spv_operand_type_t type) {
500 if (!spvIsIdType(type)) {
501 // If it is not an ID it cannot be an input ID.
502 return false;
503 }
504 switch (type) {
505 // Deny non-input IDs.
506 case SPV_OPERAND_TYPE_TYPE_ID:
507 case SPV_OPERAND_TYPE_RESULT_ID:
508 return false;
509 default:
510 return true;
511 }
512}
513
514std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
515 SpvOp opcode) {
516 std::function<bool(unsigned index)> out;
517 if (spvOpcodeGeneratesType(opcode)) {
518 // All types can use forward pointers.
519 out = [](unsigned) { return true; };
520 return out;
521 }
522 switch (opcode) {
523 case SpvOpExecutionMode:
524 case SpvOpExecutionModeId:
525 case SpvOpEntryPoint:
526 case SpvOpName:
527 case SpvOpMemberName:
528 case SpvOpSelectionMerge:
529 case SpvOpDecorate:
530 case SpvOpMemberDecorate:
531 case SpvOpDecorateId:
532 case SpvOpDecorateStringGOOGLE:
533 case SpvOpMemberDecorateStringGOOGLE:
534 case SpvOpBranch:
535 case SpvOpLoopMerge:
536 out = [](unsigned) { return true; };
537 break;
538 case SpvOpGroupDecorate:
539 case SpvOpGroupMemberDecorate:
540 case SpvOpBranchConditional:
541 case SpvOpSwitch:
542 out = [](unsigned index) { return index != 0; };
543 break;
544
545 case SpvOpFunctionCall:
546 // The Function parameter.
547 out = [](unsigned index) { return index == 2; };
548 break;
549
550 case SpvOpPhi:
551 out = [](unsigned index) { return index > 1; };
552 break;
553
554 case SpvOpEnqueueKernel:
555 // The Invoke parameter.
556 out = [](unsigned index) { return index == 8; };
557 break;
558
559 case SpvOpGetKernelNDrangeSubGroupCount:
560 case SpvOpGetKernelNDrangeMaxSubGroupSize:
561 // The Invoke parameter.
562 out = [](unsigned index) { return index == 3; };
563 break;
564
565 case SpvOpGetKernelWorkGroupSize:
566 case SpvOpGetKernelPreferredWorkGroupSizeMultiple:
567 // The Invoke parameter.
568 out = [](unsigned index) { return index == 2; };
569 break;
570 case SpvOpTypeForwardPointer:
571 out = [](unsigned index) { return index == 0; };
572 break;
573 case SpvOpTypeArray:
574 out = [](unsigned index) { return index == 1; };
575 break;
576 default:
577 out = [](unsigned) { return false; };
578 break;
579 }
580 return out;
581}
582
583std::function<bool(unsigned)> spvDbgInfoExtOperandCanBeForwardDeclaredFunction(
584 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 if (ext_type == SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) {
588 return [](unsigned) { return false; };
589 }
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 std::function<bool(unsigned index)> out;
595 if (ext_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
596 switch (OpenCLDebugInfo100Instructions(key)) {
597 case OpenCLDebugInfo100DebugFunction:
598 out = [](unsigned index) { return index == 13; };
599 break;
600 case OpenCLDebugInfo100DebugTypeComposite:
601 out = [](unsigned index) { return index >= 13; };
602 break;
603 default:
604 out = [](unsigned) { return false; };
605 break;
606 }
607 } else {
608 switch (DebugInfoInstructions(key)) {
609 case DebugInfoDebugFunction:
610 out = [](unsigned index) { return index == 13; };
611 break;
612 case DebugInfoDebugTypeComposite:
613 out = [](unsigned index) { return index >= 12; };
614 break;
615 default:
616 out = [](unsigned) { return false; };
617 break;
618 }
619 }
620 return out;
621}
622