• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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