• 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_NAMED_MAXIMUM_NUMBER_OF_REGISTERS:
224       return "named maximum number of registers";
225     case SPV_OPERAND_TYPE_RAW_ACCESS_CHAIN_OPERANDS:
226     case SPV_OPERAND_TYPE_OPTIONAL_RAW_ACCESS_CHAIN_OPERANDS:
227       return "raw access chain operands";
228     case SPV_OPERAND_TYPE_IMAGE:
229     case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
230       return "image";
231     case SPV_OPERAND_TYPE_OPTIONAL_CIV:
232       return "context-insensitive value";
233     case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
234       return "debug info flags";
235     case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
236       return "debug base type encoding";
237     case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE:
238       return "debug composite type";
239     case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER:
240       return "debug type qualifier";
241     case SPV_OPERAND_TYPE_DEBUG_OPERATION:
242       return "debug operation";
243     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS:
244       return "OpenCL.DebugInfo.100 debug info flags";
245     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
246       return "OpenCL.DebugInfo.100 debug base type encoding";
247     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE:
248       return "OpenCL.DebugInfo.100 debug composite type";
249     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER:
250       return "OpenCL.DebugInfo.100 debug type qualifier";
251     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION:
252       return "OpenCL.DebugInfo.100 debug operation";
253     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY:
254       return "OpenCL.DebugInfo.100 debug imported entity";
255 
256     // The next values are for values returned from an instruction, not actually
257     // an operand.  So the specific strings don't matter.  But let's add them
258     // for completeness and ease of testing.
259     case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER:
260       return "image channel order";
261     case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE:
262       return "image channel data type";
263 
264     case SPV_OPERAND_TYPE_FPDENORM_MODE:
265       return "FP denorm mode";
266     case SPV_OPERAND_TYPE_FPOPERATION_MODE:
267       return "FP operation mode";
268     case SPV_OPERAND_TYPE_QUANTIZATION_MODES:
269       return "quantization mode";
270     case SPV_OPERAND_TYPE_OVERFLOW_MODES:
271       return "overflow 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_LITERAL_FLOAT:
318     case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER:
319     case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER:
320     case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
321     case SPV_OPERAND_TYPE_LITERAL_STRING:
322     case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
323     case SPV_OPERAND_TYPE_EXECUTION_MODEL:
324     case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
325     case SPV_OPERAND_TYPE_MEMORY_MODEL:
326     case SPV_OPERAND_TYPE_EXECUTION_MODE:
327     case SPV_OPERAND_TYPE_STORAGE_CLASS:
328     case SPV_OPERAND_TYPE_DIMENSIONALITY:
329     case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
330     case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
331     case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT:
332     case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER:
333     case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE:
334     case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
335     case SPV_OPERAND_TYPE_LINKAGE_TYPE:
336     case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
337     case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
338     case SPV_OPERAND_TYPE_DECORATION:
339     case SPV_OPERAND_TYPE_BUILT_IN:
340     case SPV_OPERAND_TYPE_GROUP_OPERATION:
341     case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
342     case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
343     case SPV_OPERAND_TYPE_CAPABILITY:
344     case SPV_OPERAND_TYPE_RAY_FLAGS:
345     case SPV_OPERAND_TYPE_RAY_QUERY_INTERSECTION:
346     case SPV_OPERAND_TYPE_RAY_QUERY_COMMITTED_INTERSECTION_TYPE:
347     case SPV_OPERAND_TYPE_RAY_QUERY_CANDIDATE_INTERSECTION_TYPE:
348     case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
349     case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE:
350     case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER:
351     case SPV_OPERAND_TYPE_DEBUG_OPERATION:
352     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
353     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_COMPOSITE_TYPE:
354     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_TYPE_QUALIFIER:
355     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION:
356     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_IMPORTED_ENTITY:
357     case SPV_OPERAND_TYPE_FPDENORM_MODE:
358     case SPV_OPERAND_TYPE_FPOPERATION_MODE:
359     case SPV_OPERAND_TYPE_QUANTIZATION_MODES:
360     case SPV_OPERAND_TYPE_OVERFLOW_MODES:
361     case SPV_OPERAND_TYPE_PACKED_VECTOR_FORMAT:
362     case SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_LAYOUT:
363     case SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_USE:
364     case SPV_OPERAND_TYPE_INITIALIZATION_MODE_QUALIFIER:
365     case SPV_OPERAND_TYPE_HOST_ACCESS_QUALIFIER:
366     case SPV_OPERAND_TYPE_LOAD_CACHE_CONTROL:
367     case SPV_OPERAND_TYPE_STORE_CACHE_CONTROL:
368     case SPV_OPERAND_TYPE_NAMED_MAXIMUM_NUMBER_OF_REGISTERS:
369       return true;
370     default:
371       break;
372   }
373   return false;
374 }
375 
spvOperandIsConcreteMask(spv_operand_type_t type)376 bool spvOperandIsConcreteMask(spv_operand_type_t type) {
377   switch (type) {
378     case SPV_OPERAND_TYPE_IMAGE:
379     case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
380     case SPV_OPERAND_TYPE_SELECTION_CONTROL:
381     case SPV_OPERAND_TYPE_LOOP_CONTROL:
382     case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
383     case SPV_OPERAND_TYPE_MEMORY_ACCESS:
384     case SPV_OPERAND_TYPE_FRAGMENT_SHADING_RATE:
385     case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
386     case SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_INFO_FLAGS:
387     case SPV_OPERAND_TYPE_COOPERATIVE_MATRIX_OPERANDS:
388     case SPV_OPERAND_TYPE_RAW_ACCESS_CHAIN_OPERANDS:
389       return true;
390     default:
391       break;
392   }
393   return false;
394 }
395 
spvOperandIsOptional(spv_operand_type_t type)396 bool spvOperandIsOptional(spv_operand_type_t type) {
397   switch (type) {
398     case SPV_OPERAND_TYPE_OPTIONAL_ID:
399     case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
400     case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
401     case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER:
402     case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER:
403     case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
404     case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING:
405     case SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER:
406     case SPV_OPERAND_TYPE_OPTIONAL_PACKED_VECTOR_FORMAT:
407     case SPV_OPERAND_TYPE_OPTIONAL_COOPERATIVE_MATRIX_OPERANDS:
408     case SPV_OPERAND_TYPE_OPTIONAL_CIV:
409     case SPV_OPERAND_TYPE_OPTIONAL_RAW_ACCESS_CHAIN_OPERANDS:
410       return true;
411     default:
412       break;
413   }
414   // Any variable operand is also optional.
415   return spvOperandIsVariable(type);
416 }
417 
spvOperandIsVariable(spv_operand_type_t type)418 bool spvOperandIsVariable(spv_operand_type_t type) {
419   switch (type) {
420     case SPV_OPERAND_TYPE_VARIABLE_ID:
421     case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER:
422     case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID:
423     case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER:
424       return true;
425     default:
426       break;
427   }
428   return false;
429 }
430 
spvExpandOperandSequenceOnce(spv_operand_type_t type,spv_operand_pattern_t * pattern)431 bool spvExpandOperandSequenceOnce(spv_operand_type_t type,
432                                   spv_operand_pattern_t* pattern) {
433   switch (type) {
434     case SPV_OPERAND_TYPE_VARIABLE_ID:
435       pattern->push_back(type);
436       pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_ID);
437       return true;
438     case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER:
439       pattern->push_back(type);
440       pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER);
441       return true;
442     case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID:
443       // Represents Zero or more (Literal number, Id) pairs,
444       // where the literal number must be a scalar integer.
445       pattern->push_back(type);
446       pattern->push_back(SPV_OPERAND_TYPE_ID);
447       pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER);
448       return true;
449     case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER:
450       // Represents Zero or more (Id, Literal number) pairs.
451       pattern->push_back(type);
452       pattern->push_back(SPV_OPERAND_TYPE_LITERAL_INTEGER);
453       pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_ID);
454       return true;
455     default:
456       break;
457   }
458   return false;
459 }
460 
spvTakeFirstMatchableOperand(spv_operand_pattern_t * pattern)461 spv_operand_type_t spvTakeFirstMatchableOperand(
462     spv_operand_pattern_t* pattern) {
463   assert(!pattern->empty());
464   spv_operand_type_t result;
465   do {
466     result = pattern->back();
467     pattern->pop_back();
468   } while (spvExpandOperandSequenceOnce(result, pattern));
469   return result;
470 }
471 
spvAlternatePatternFollowingImmediate(const spv_operand_pattern_t & pattern)472 spv_operand_pattern_t spvAlternatePatternFollowingImmediate(
473     const spv_operand_pattern_t& pattern) {
474   auto it =
475       std::find(pattern.crbegin(), pattern.crend(), SPV_OPERAND_TYPE_RESULT_ID);
476   if (it != pattern.crend()) {
477     spv_operand_pattern_t alternatePattern(it - pattern.crbegin() + 2,
478                                            SPV_OPERAND_TYPE_OPTIONAL_CIV);
479     alternatePattern[1] = SPV_OPERAND_TYPE_RESULT_ID;
480     return alternatePattern;
481   }
482 
483   // No result-id found, so just expect CIVs.
484   return {SPV_OPERAND_TYPE_OPTIONAL_CIV};
485 }
486 
spvIsIdType(spv_operand_type_t type)487 bool spvIsIdType(spv_operand_type_t type) {
488   switch (type) {
489     case SPV_OPERAND_TYPE_ID:
490     case SPV_OPERAND_TYPE_TYPE_ID:
491     case SPV_OPERAND_TYPE_RESULT_ID:
492     case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
493     case SPV_OPERAND_TYPE_SCOPE_ID:
494       return true;
495     default:
496       return false;
497   }
498 }
499 
spvIsInIdType(spv_operand_type_t type)500 bool spvIsInIdType(spv_operand_type_t type) {
501   if (!spvIsIdType(type)) {
502     // If it is not an ID it cannot be an input ID.
503     return false;
504   }
505   switch (type) {
506     // Deny non-input IDs.
507     case SPV_OPERAND_TYPE_TYPE_ID:
508     case SPV_OPERAND_TYPE_RESULT_ID:
509       return false;
510     default:
511       return true;
512   }
513 }
514 
spvOperandCanBeForwardDeclaredFunction(spv::Op opcode)515 std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
516     spv::Op opcode) {
517   std::function<bool(unsigned index)> out;
518   if (spvOpcodeGeneratesType(opcode)) {
519     // All types can use forward pointers.
520     out = [](unsigned) { return true; };
521     return out;
522   }
523   switch (opcode) {
524     case spv::Op::OpExecutionMode:
525     case spv::Op::OpExecutionModeId:
526     case spv::Op::OpEntryPoint:
527     case spv::Op::OpName:
528     case spv::Op::OpMemberName:
529     case spv::Op::OpSelectionMerge:
530     case spv::Op::OpDecorate:
531     case spv::Op::OpMemberDecorate:
532     case spv::Op::OpDecorateId:
533     case spv::Op::OpDecorateStringGOOGLE:
534     case spv::Op::OpMemberDecorateStringGOOGLE:
535     case spv::Op::OpBranch:
536     case spv::Op::OpLoopMerge:
537       out = [](unsigned) { return true; };
538       break;
539     case spv::Op::OpGroupDecorate:
540     case spv::Op::OpGroupMemberDecorate:
541     case spv::Op::OpBranchConditional:
542     case spv::Op::OpSwitch:
543       out = [](unsigned index) { return index != 0; };
544       break;
545 
546     case spv::Op::OpFunctionCall:
547       // The Function parameter.
548       out = [](unsigned index) { return index == 2; };
549       break;
550 
551     case spv::Op::OpPhi:
552       out = [](unsigned index) { return index > 1; };
553       break;
554 
555     case spv::Op::OpEnqueueKernel:
556       // The Invoke parameter.
557       out = [](unsigned index) { return index == 8; };
558       break;
559 
560     case spv::Op::OpGetKernelNDrangeSubGroupCount:
561     case spv::Op::OpGetKernelNDrangeMaxSubGroupSize:
562       // The Invoke parameter.
563       out = [](unsigned index) { return index == 3; };
564       break;
565 
566     case spv::Op::OpGetKernelWorkGroupSize:
567     case spv::Op::OpGetKernelPreferredWorkGroupSizeMultiple:
568       // The Invoke parameter.
569       out = [](unsigned index) { return index == 2; };
570       break;
571     case spv::Op::OpTypeForwardPointer:
572       out = [](unsigned index) { return index == 0; };
573       break;
574     case spv::Op::OpTypeArray:
575       out = [](unsigned index) { return index == 1; };
576       break;
577     default:
578       out = [](unsigned) { return false; };
579       break;
580   }
581   return out;
582 }
583 
spvDbgInfoExtOperandCanBeForwardDeclaredFunction(spv_ext_inst_type_t ext_type,uint32_t key)584 std::function<bool(unsigned)> spvDbgInfoExtOperandCanBeForwardDeclaredFunction(
585     spv_ext_inst_type_t ext_type, uint32_t key) {
586   // The Vulkan debug info extended instruction set is non-semantic so allows no
587   // forward references ever
588   if (ext_type == SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) {
589     return [](unsigned) { return false; };
590   }
591 
592   // TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/532): Forward
593   // references for debug info instructions are still in discussion. We must
594   // update the following lines of code when we conclude the spec.
595   std::function<bool(unsigned index)> out;
596   if (ext_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
597     switch (OpenCLDebugInfo100Instructions(key)) {
598       case OpenCLDebugInfo100DebugFunction:
599         out = [](unsigned index) { return index == 13; };
600         break;
601       case OpenCLDebugInfo100DebugTypeComposite:
602         out = [](unsigned index) { return index >= 13; };
603         break;
604       default:
605         out = [](unsigned) { return false; };
606         break;
607     }
608   } else {
609     switch (DebugInfoInstructions(key)) {
610       case DebugInfoDebugFunction:
611         out = [](unsigned index) { return index == 13; };
612         break;
613       case DebugInfoDebugTypeComposite:
614         out = [](unsigned index) { return index >= 12; };
615         break;
616       default:
617         out = [](unsigned) { return false; };
618         break;
619     }
620   }
621   return out;
622 }
623