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