Coverage Report

Created: 2023-03-01 07:33

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