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