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