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