1 // Copyright (c) 2015-2016 The Khronos Group Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "source/val/validation_state.h"
16
17 #include <cassert>
18 #include <stack>
19 #include <utility>
20
21 #include "source/opcode.h"
22 #include "source/spirv_constant.h"
23 #include "source/spirv_target_env.h"
24 #include "source/val/basic_block.h"
25 #include "source/val/construct.h"
26 #include "source/val/function.h"
27 #include "spirv-tools/libspirv.h"
28
29 namespace spvtools {
30 namespace val {
31 namespace {
32
InstructionLayoutSection(ModuleLayoutSection current_section,SpvOp op)33 ModuleLayoutSection InstructionLayoutSection(
34 ModuleLayoutSection current_section, SpvOp op) {
35 // See Section 2.4
36 if (spvOpcodeGeneratesType(op) || spvOpcodeIsConstant(op))
37 return kLayoutTypes;
38
39 switch (op) {
40 case SpvOpCapability:
41 return kLayoutCapabilities;
42 case SpvOpExtension:
43 return kLayoutExtensions;
44 case SpvOpExtInstImport:
45 return kLayoutExtInstImport;
46 case SpvOpMemoryModel:
47 return kLayoutMemoryModel;
48 case SpvOpEntryPoint:
49 return kLayoutEntryPoint;
50 case SpvOpExecutionMode:
51 case SpvOpExecutionModeId:
52 return kLayoutExecutionMode;
53 case SpvOpSourceContinued:
54 case SpvOpSource:
55 case SpvOpSourceExtension:
56 case SpvOpString:
57 return kLayoutDebug1;
58 case SpvOpName:
59 case SpvOpMemberName:
60 return kLayoutDebug2;
61 case SpvOpModuleProcessed:
62 return kLayoutDebug3;
63 case SpvOpDecorate:
64 case SpvOpMemberDecorate:
65 case SpvOpGroupDecorate:
66 case SpvOpGroupMemberDecorate:
67 case SpvOpDecorationGroup:
68 case SpvOpDecorateId:
69 case SpvOpDecorateStringGOOGLE:
70 case SpvOpMemberDecorateStringGOOGLE:
71 return kLayoutAnnotations;
72 case SpvOpTypeForwardPointer:
73 return kLayoutTypes;
74 case SpvOpVariable:
75 if (current_section == kLayoutTypes) return kLayoutTypes;
76 return kLayoutFunctionDefinitions;
77 case SpvOpExtInst:
78 // SpvOpExtInst is only allowed in types section for certain extended
79 // instruction sets. This will be checked separately.
80 if (current_section == kLayoutTypes) return kLayoutTypes;
81 return kLayoutFunctionDefinitions;
82 case SpvOpLine:
83 case SpvOpNoLine:
84 case SpvOpUndef:
85 if (current_section == kLayoutTypes) return kLayoutTypes;
86 return kLayoutFunctionDefinitions;
87 case SpvOpFunction:
88 case SpvOpFunctionParameter:
89 case SpvOpFunctionEnd:
90 if (current_section == kLayoutFunctionDeclarations)
91 return kLayoutFunctionDeclarations;
92 return kLayoutFunctionDefinitions;
93 default:
94 break;
95 }
96 return kLayoutFunctionDefinitions;
97 }
98
IsInstructionInLayoutSection(ModuleLayoutSection layout,SpvOp op)99 bool IsInstructionInLayoutSection(ModuleLayoutSection layout, SpvOp op) {
100 return layout == InstructionLayoutSection(layout, op);
101 }
102
103 // Counts the number of instructions and functions in the file.
CountInstructions(void * user_data,const spv_parsed_instruction_t * inst)104 spv_result_t CountInstructions(void* user_data,
105 const spv_parsed_instruction_t* inst) {
106 ValidationState_t& _ = *(reinterpret_cast<ValidationState_t*>(user_data));
107 if (inst->opcode == SpvOpFunction) _.increment_total_functions();
108 _.increment_total_instructions();
109
110 return SPV_SUCCESS;
111 }
112
setHeader(void * user_data,spv_endianness_t,uint32_t,uint32_t version,uint32_t generator,uint32_t id_bound,uint32_t)113 spv_result_t setHeader(void* user_data, spv_endianness_t, uint32_t,
114 uint32_t version, uint32_t generator, uint32_t id_bound,
115 uint32_t) {
116 ValidationState_t& vstate =
117 *(reinterpret_cast<ValidationState_t*>(user_data));
118 vstate.setIdBound(id_bound);
119 vstate.setGenerator(generator);
120 vstate.setVersion(version);
121
122 return SPV_SUCCESS;
123 }
124
125 // Add features based on SPIR-V core version number.
UpdateFeaturesBasedOnSpirvVersion(ValidationState_t::Feature * features,uint32_t version)126 void UpdateFeaturesBasedOnSpirvVersion(ValidationState_t::Feature* features,
127 uint32_t version) {
128 assert(features);
129 if (version >= SPV_SPIRV_VERSION_WORD(1, 4)) {
130 features->select_between_composites = true;
131 features->copy_memory_permits_two_memory_accesses = true;
132 features->uconvert_spec_constant_op = true;
133 features->nonwritable_var_in_function_or_private = true;
134 }
135 }
136
137 } // namespace
138
ValidationState_t(const spv_const_context ctx,const spv_const_validator_options opt,const uint32_t * words,const size_t num_words,const uint32_t max_warnings)139 ValidationState_t::ValidationState_t(const spv_const_context ctx,
140 const spv_const_validator_options opt,
141 const uint32_t* words,
142 const size_t num_words,
143 const uint32_t max_warnings)
144 : context_(ctx),
145 options_(opt),
146 words_(words),
147 num_words_(num_words),
148 unresolved_forward_ids_{},
149 operand_names_{},
150 current_layout_section_(kLayoutCapabilities),
151 module_functions_(),
152 module_capabilities_(),
153 module_extensions_(),
154 ordered_instructions_(),
155 all_definitions_(),
156 global_vars_(),
157 local_vars_(),
158 struct_nesting_depth_(),
159 struct_has_nested_blockorbufferblock_struct_(),
160 grammar_(ctx),
161 addressing_model_(SpvAddressingModelMax),
162 memory_model_(SpvMemoryModelMax),
163 pointer_size_and_alignment_(0),
164 in_function_(false),
165 num_of_warnings_(0),
166 max_num_of_warnings_(max_warnings) {
167 assert(opt && "Validator options may not be Null.");
168
169 const auto env = context_->target_env;
170
171 if (spvIsVulkanEnv(env)) {
172 // Vulkan 1.1 includes VK_KHR_relaxed_block_layout in core.
173 if (env != SPV_ENV_VULKAN_1_0) {
174 features_.env_relaxed_block_layout = true;
175 }
176 }
177
178 // Only attempt to count if we have words, otherwise let the other validation
179 // fail and generate an error.
180 if (num_words > 0) {
181 // Count the number of instructions in the binary.
182 // This parse should not produce any error messages. Hijack the context and
183 // replace the message consumer so that we do not pollute any state in input
184 // consumer.
185 spv_context_t hijacked_context = *ctx;
186 hijacked_context.consumer = [](spv_message_level_t, const char*,
__anonbf7ee5f90202(spv_message_level_t, const char*, const spv_position_t&, const char*) 187 const spv_position_t&, const char*) {};
188 spvBinaryParse(&hijacked_context, this, words, num_words, setHeader,
189 CountInstructions,
190 /* diagnostic = */ nullptr);
191 preallocateStorage();
192 }
193 UpdateFeaturesBasedOnSpirvVersion(&features_, version_);
194
195 friendly_mapper_ = spvtools::MakeUnique<spvtools::FriendlyNameMapper>(
196 context_, words_, num_words_);
197 name_mapper_ = friendly_mapper_->GetNameMapper();
198 }
199
preallocateStorage()200 void ValidationState_t::preallocateStorage() {
201 ordered_instructions_.reserve(total_instructions_);
202 module_functions_.reserve(total_functions_);
203 }
204
ForwardDeclareId(uint32_t id)205 spv_result_t ValidationState_t::ForwardDeclareId(uint32_t id) {
206 unresolved_forward_ids_.insert(id);
207 return SPV_SUCCESS;
208 }
209
RemoveIfForwardDeclared(uint32_t id)210 spv_result_t ValidationState_t::RemoveIfForwardDeclared(uint32_t id) {
211 unresolved_forward_ids_.erase(id);
212 return SPV_SUCCESS;
213 }
214
RegisterForwardPointer(uint32_t id)215 spv_result_t ValidationState_t::RegisterForwardPointer(uint32_t id) {
216 forward_pointer_ids_.insert(id);
217 return SPV_SUCCESS;
218 }
219
IsForwardPointer(uint32_t id) const220 bool ValidationState_t::IsForwardPointer(uint32_t id) const {
221 return (forward_pointer_ids_.find(id) != forward_pointer_ids_.end());
222 }
223
AssignNameToId(uint32_t id,std::string name)224 void ValidationState_t::AssignNameToId(uint32_t id, std::string name) {
225 operand_names_[id] = name;
226 }
227
getIdName(uint32_t id) const228 std::string ValidationState_t::getIdName(uint32_t id) const {
229 const std::string id_name = name_mapper_(id);
230
231 std::stringstream out;
232 out << id << "[%" << id_name << "]";
233 return out.str();
234 }
235
unresolved_forward_id_count() const236 size_t ValidationState_t::unresolved_forward_id_count() const {
237 return unresolved_forward_ids_.size();
238 }
239
UnresolvedForwardIds() const240 std::vector<uint32_t> ValidationState_t::UnresolvedForwardIds() const {
241 std::vector<uint32_t> out(std::begin(unresolved_forward_ids_),
242 std::end(unresolved_forward_ids_));
243 return out;
244 }
245
IsDefinedId(uint32_t id) const246 bool ValidationState_t::IsDefinedId(uint32_t id) const {
247 return all_definitions_.find(id) != std::end(all_definitions_);
248 }
249
FindDef(uint32_t id) const250 const Instruction* ValidationState_t::FindDef(uint32_t id) const {
251 auto it = all_definitions_.find(id);
252 if (it == all_definitions_.end()) return nullptr;
253 return it->second;
254 }
255
FindDef(uint32_t id)256 Instruction* ValidationState_t::FindDef(uint32_t id) {
257 auto it = all_definitions_.find(id);
258 if (it == all_definitions_.end()) return nullptr;
259 return it->second;
260 }
261
current_layout_section() const262 ModuleLayoutSection ValidationState_t::current_layout_section() const {
263 return current_layout_section_;
264 }
265
ProgressToNextLayoutSectionOrder()266 void ValidationState_t::ProgressToNextLayoutSectionOrder() {
267 // Guard against going past the last element(kLayoutFunctionDefinitions)
268 if (current_layout_section_ <= kLayoutFunctionDefinitions) {
269 current_layout_section_ =
270 static_cast<ModuleLayoutSection>(current_layout_section_ + 1);
271 }
272 }
273
IsOpcodeInPreviousLayoutSection(SpvOp op)274 bool ValidationState_t::IsOpcodeInPreviousLayoutSection(SpvOp op) {
275 ModuleLayoutSection section =
276 InstructionLayoutSection(current_layout_section_, op);
277 return section < current_layout_section_;
278 }
279
IsOpcodeInCurrentLayoutSection(SpvOp op)280 bool ValidationState_t::IsOpcodeInCurrentLayoutSection(SpvOp op) {
281 return IsInstructionInLayoutSection(current_layout_section_, op);
282 }
283
diag(spv_result_t error_code,const Instruction * inst)284 DiagnosticStream ValidationState_t::diag(spv_result_t error_code,
285 const Instruction* inst) {
286 if (error_code == SPV_WARNING) {
287 if (num_of_warnings_ == max_num_of_warnings_) {
288 DiagnosticStream({0, 0, 0}, context_->consumer, "", error_code)
289 << "Other warnings have been suppressed.\n";
290 }
291 if (num_of_warnings_ >= max_num_of_warnings_) {
292 return DiagnosticStream({0, 0, 0}, nullptr, "", error_code);
293 }
294 ++num_of_warnings_;
295 }
296
297 std::string disassembly;
298 if (inst) disassembly = Disassemble(*inst);
299
300 return DiagnosticStream({0, 0, inst ? inst->LineNum() : 0},
301 context_->consumer, disassembly, error_code);
302 }
303
functions()304 std::vector<Function>& ValidationState_t::functions() {
305 return module_functions_;
306 }
307
current_function()308 Function& ValidationState_t::current_function() {
309 assert(in_function_body());
310 return module_functions_.back();
311 }
312
current_function() const313 const Function& ValidationState_t::current_function() const {
314 assert(in_function_body());
315 return module_functions_.back();
316 }
317
function(uint32_t id) const318 const Function* ValidationState_t::function(uint32_t id) const {
319 const auto it = id_to_function_.find(id);
320 if (it == id_to_function_.end()) return nullptr;
321 return it->second;
322 }
323
function(uint32_t id)324 Function* ValidationState_t::function(uint32_t id) {
325 auto it = id_to_function_.find(id);
326 if (it == id_to_function_.end()) return nullptr;
327 return it->second;
328 }
329
in_function_body() const330 bool ValidationState_t::in_function_body() const { return in_function_; }
331
in_block() const332 bool ValidationState_t::in_block() const {
333 return module_functions_.empty() == false &&
334 module_functions_.back().current_block() != nullptr;
335 }
336
RegisterCapability(SpvCapability cap)337 void ValidationState_t::RegisterCapability(SpvCapability cap) {
338 // Avoid redundant work. Otherwise the recursion could induce work
339 // quadrdatic in the capability dependency depth. (Ok, not much, but
340 // it's something.)
341 if (module_capabilities_.Contains(cap)) return;
342
343 module_capabilities_.Add(cap);
344 spv_operand_desc desc;
345 if (SPV_SUCCESS ==
346 grammar_.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY, cap, &desc)) {
347 CapabilitySet(desc->numCapabilities, desc->capabilities)
348 .ForEach([this](SpvCapability c) { RegisterCapability(c); });
349 }
350
351 switch (cap) {
352 case SpvCapabilityKernel:
353 features_.group_ops_reduce_and_scans = true;
354 break;
355 case SpvCapabilityInt8:
356 features_.use_int8_type = true;
357 features_.declare_int8_type = true;
358 break;
359 case SpvCapabilityStorageBuffer8BitAccess:
360 case SpvCapabilityUniformAndStorageBuffer8BitAccess:
361 case SpvCapabilityStoragePushConstant8:
362 case SpvCapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR:
363 features_.declare_int8_type = true;
364 break;
365 case SpvCapabilityInt16:
366 features_.declare_int16_type = true;
367 break;
368 case SpvCapabilityFloat16:
369 case SpvCapabilityFloat16Buffer:
370 features_.declare_float16_type = true;
371 break;
372 case SpvCapabilityStorageUniformBufferBlock16:
373 case SpvCapabilityStorageUniform16:
374 case SpvCapabilityStoragePushConstant16:
375 case SpvCapabilityStorageInputOutput16:
376 case SpvCapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR:
377 features_.declare_int16_type = true;
378 features_.declare_float16_type = true;
379 features_.free_fp_rounding_mode = true;
380 break;
381 case SpvCapabilityVariablePointers:
382 features_.variable_pointers = true;
383 features_.variable_pointers_storage_buffer = true;
384 break;
385 case SpvCapabilityVariablePointersStorageBuffer:
386 features_.variable_pointers_storage_buffer = true;
387 break;
388 default:
389 break;
390 }
391 }
392
RegisterExtension(Extension ext)393 void ValidationState_t::RegisterExtension(Extension ext) {
394 if (module_extensions_.Contains(ext)) return;
395
396 module_extensions_.Add(ext);
397
398 switch (ext) {
399 case kSPV_AMD_gpu_shader_half_float:
400 case kSPV_AMD_gpu_shader_half_float_fetch:
401 // SPV_AMD_gpu_shader_half_float enables float16 type.
402 // https://github.com/KhronosGroup/SPIRV-Tools/issues/1375
403 features_.declare_float16_type = true;
404 break;
405 case kSPV_AMD_gpu_shader_int16:
406 // This is not yet in the extension, but it's recommended for it.
407 // See https://github.com/KhronosGroup/glslang/issues/848
408 features_.uconvert_spec_constant_op = true;
409 break;
410 case kSPV_AMD_shader_ballot:
411 // The grammar doesn't encode the fact that SPV_AMD_shader_ballot
412 // enables the use of group operations Reduce, InclusiveScan,
413 // and ExclusiveScan. Enable it manually.
414 // https://github.com/KhronosGroup/SPIRV-Tools/issues/991
415 features_.group_ops_reduce_and_scans = true;
416 break;
417 default:
418 break;
419 }
420 }
421
HasAnyOfCapabilities(const CapabilitySet & capabilities) const422 bool ValidationState_t::HasAnyOfCapabilities(
423 const CapabilitySet& capabilities) const {
424 return module_capabilities_.HasAnyOf(capabilities);
425 }
426
HasAnyOfExtensions(const ExtensionSet & extensions) const427 bool ValidationState_t::HasAnyOfExtensions(
428 const ExtensionSet& extensions) const {
429 return module_extensions_.HasAnyOf(extensions);
430 }
431
set_addressing_model(SpvAddressingModel am)432 void ValidationState_t::set_addressing_model(SpvAddressingModel am) {
433 addressing_model_ = am;
434 switch (am) {
435 case SpvAddressingModelPhysical32:
436 pointer_size_and_alignment_ = 4;
437 break;
438 default:
439 // fall through
440 case SpvAddressingModelPhysical64:
441 case SpvAddressingModelPhysicalStorageBuffer64EXT:
442 pointer_size_and_alignment_ = 8;
443 break;
444 }
445 }
446
addressing_model() const447 SpvAddressingModel ValidationState_t::addressing_model() const {
448 return addressing_model_;
449 }
450
set_memory_model(SpvMemoryModel mm)451 void ValidationState_t::set_memory_model(SpvMemoryModel mm) {
452 memory_model_ = mm;
453 }
454
memory_model() const455 SpvMemoryModel ValidationState_t::memory_model() const { return memory_model_; }
456
RegisterFunction(uint32_t id,uint32_t ret_type_id,SpvFunctionControlMask function_control,uint32_t function_type_id)457 spv_result_t ValidationState_t::RegisterFunction(
458 uint32_t id, uint32_t ret_type_id, SpvFunctionControlMask function_control,
459 uint32_t function_type_id) {
460 assert(in_function_body() == false &&
461 "RegisterFunction can only be called when parsing the binary outside "
462 "of another function");
463 in_function_ = true;
464 module_functions_.emplace_back(id, ret_type_id, function_control,
465 function_type_id);
466 id_to_function_.emplace(id, ¤t_function());
467
468 // TODO(umar): validate function type and type_id
469
470 return SPV_SUCCESS;
471 }
472
RegisterFunctionEnd()473 spv_result_t ValidationState_t::RegisterFunctionEnd() {
474 assert(in_function_body() == true &&
475 "RegisterFunctionEnd can only be called when parsing the binary "
476 "inside of another function");
477 assert(in_block() == false &&
478 "RegisterFunctionParameter can only be called when parsing the binary "
479 "ouside of a block");
480 current_function().RegisterFunctionEnd();
481 in_function_ = false;
482 return SPV_SUCCESS;
483 }
484
AddOrderedInstruction(const spv_parsed_instruction_t * inst)485 Instruction* ValidationState_t::AddOrderedInstruction(
486 const spv_parsed_instruction_t* inst) {
487 ordered_instructions_.emplace_back(inst);
488 ordered_instructions_.back().SetLineNum(ordered_instructions_.size());
489 return &ordered_instructions_.back();
490 }
491
492 // Improves diagnostic messages by collecting names of IDs
RegisterDebugInstruction(const Instruction * inst)493 void ValidationState_t::RegisterDebugInstruction(const Instruction* inst) {
494 switch (inst->opcode()) {
495 case SpvOpName: {
496 const auto target = inst->GetOperandAs<uint32_t>(0);
497 const auto* str = reinterpret_cast<const char*>(inst->words().data() +
498 inst->operand(1).offset);
499 AssignNameToId(target, str);
500 break;
501 }
502 case SpvOpMemberName: {
503 const auto target = inst->GetOperandAs<uint32_t>(0);
504 const auto* str = reinterpret_cast<const char*>(inst->words().data() +
505 inst->operand(2).offset);
506 AssignNameToId(target, str);
507 break;
508 }
509 case SpvOpSourceContinued:
510 case SpvOpSource:
511 case SpvOpSourceExtension:
512 case SpvOpString:
513 case SpvOpLine:
514 case SpvOpNoLine:
515 default:
516 break;
517 }
518 }
519
RegisterInstruction(Instruction * inst)520 void ValidationState_t::RegisterInstruction(Instruction* inst) {
521 if (inst->id()) all_definitions_.insert(std::make_pair(inst->id(), inst));
522
523 // If the instruction is using an OpTypeSampledImage as an operand, it should
524 // be recorded. The validator will ensure that all usages of an
525 // OpTypeSampledImage and its definition are in the same basic block.
526 for (uint16_t i = 0; i < inst->operands().size(); ++i) {
527 const spv_parsed_operand_t& operand = inst->operand(i);
528 if (SPV_OPERAND_TYPE_ID == operand.type) {
529 const uint32_t operand_word = inst->word(operand.offset);
530 Instruction* operand_inst = FindDef(operand_word);
531 if (operand_inst && SpvOpSampledImage == operand_inst->opcode()) {
532 RegisterSampledImageConsumer(operand_word, inst);
533 }
534 }
535 }
536 }
537
getSampledImageConsumers(uint32_t sampled_image_id) const538 std::vector<Instruction*> ValidationState_t::getSampledImageConsumers(
539 uint32_t sampled_image_id) const {
540 std::vector<Instruction*> result;
541 auto iter = sampled_image_consumers_.find(sampled_image_id);
542 if (iter != sampled_image_consumers_.end()) {
543 result = iter->second;
544 }
545 return result;
546 }
547
RegisterSampledImageConsumer(uint32_t sampled_image_id,Instruction * consumer)548 void ValidationState_t::RegisterSampledImageConsumer(uint32_t sampled_image_id,
549 Instruction* consumer) {
550 sampled_image_consumers_[sampled_image_id].push_back(consumer);
551 }
552
getIdBound() const553 uint32_t ValidationState_t::getIdBound() const { return id_bound_; }
554
setIdBound(const uint32_t bound)555 void ValidationState_t::setIdBound(const uint32_t bound) { id_bound_ = bound; }
556
RegisterUniqueTypeDeclaration(const Instruction * inst)557 bool ValidationState_t::RegisterUniqueTypeDeclaration(const Instruction* inst) {
558 std::vector<uint32_t> key;
559 key.push_back(static_cast<uint32_t>(inst->opcode()));
560 for (size_t index = 0; index < inst->operands().size(); ++index) {
561 const spv_parsed_operand_t& operand = inst->operand(index);
562
563 if (operand.type == SPV_OPERAND_TYPE_RESULT_ID) continue;
564
565 const int words_begin = operand.offset;
566 const int words_end = words_begin + operand.num_words;
567 assert(words_end <= static_cast<int>(inst->words().size()));
568
569 key.insert(key.end(), inst->words().begin() + words_begin,
570 inst->words().begin() + words_end);
571 }
572
573 return unique_type_declarations_.insert(std::move(key)).second;
574 }
575
GetTypeId(uint32_t id) const576 uint32_t ValidationState_t::GetTypeId(uint32_t id) const {
577 const Instruction* inst = FindDef(id);
578 return inst ? inst->type_id() : 0;
579 }
580
GetIdOpcode(uint32_t id) const581 SpvOp ValidationState_t::GetIdOpcode(uint32_t id) const {
582 const Instruction* inst = FindDef(id);
583 return inst ? inst->opcode() : SpvOpNop;
584 }
585
GetComponentType(uint32_t id) const586 uint32_t ValidationState_t::GetComponentType(uint32_t id) const {
587 const Instruction* inst = FindDef(id);
588 assert(inst);
589
590 switch (inst->opcode()) {
591 case SpvOpTypeFloat:
592 case SpvOpTypeInt:
593 case SpvOpTypeBool:
594 return id;
595
596 case SpvOpTypeVector:
597 return inst->word(2);
598
599 case SpvOpTypeMatrix:
600 return GetComponentType(inst->word(2));
601
602 case SpvOpTypeCooperativeMatrixNV:
603 return inst->word(2);
604
605 default:
606 break;
607 }
608
609 if (inst->type_id()) return GetComponentType(inst->type_id());
610
611 assert(0);
612 return 0;
613 }
614
GetDimension(uint32_t id) const615 uint32_t ValidationState_t::GetDimension(uint32_t id) const {
616 const Instruction* inst = FindDef(id);
617 assert(inst);
618
619 switch (inst->opcode()) {
620 case SpvOpTypeFloat:
621 case SpvOpTypeInt:
622 case SpvOpTypeBool:
623 return 1;
624
625 case SpvOpTypeVector:
626 case SpvOpTypeMatrix:
627 return inst->word(3);
628
629 case SpvOpTypeCooperativeMatrixNV:
630 // Actual dimension isn't known, return 0
631 return 0;
632
633 default:
634 break;
635 }
636
637 if (inst->type_id()) return GetDimension(inst->type_id());
638
639 assert(0);
640 return 0;
641 }
642
GetBitWidth(uint32_t id) const643 uint32_t ValidationState_t::GetBitWidth(uint32_t id) const {
644 const uint32_t component_type_id = GetComponentType(id);
645 const Instruction* inst = FindDef(component_type_id);
646 assert(inst);
647
648 if (inst->opcode() == SpvOpTypeFloat || inst->opcode() == SpvOpTypeInt)
649 return inst->word(2);
650
651 if (inst->opcode() == SpvOpTypeBool) return 1;
652
653 assert(0);
654 return 0;
655 }
656
IsVoidType(uint32_t id) const657 bool ValidationState_t::IsVoidType(uint32_t id) const {
658 const Instruction* inst = FindDef(id);
659 assert(inst);
660 return inst->opcode() == SpvOpTypeVoid;
661 }
662
IsFloatScalarType(uint32_t id) const663 bool ValidationState_t::IsFloatScalarType(uint32_t id) const {
664 const Instruction* inst = FindDef(id);
665 assert(inst);
666 return inst->opcode() == SpvOpTypeFloat;
667 }
668
IsFloatVectorType(uint32_t id) const669 bool ValidationState_t::IsFloatVectorType(uint32_t id) const {
670 const Instruction* inst = FindDef(id);
671 assert(inst);
672
673 if (inst->opcode() == SpvOpTypeVector) {
674 return IsFloatScalarType(GetComponentType(id));
675 }
676
677 return false;
678 }
679
IsFloatScalarOrVectorType(uint32_t id) const680 bool ValidationState_t::IsFloatScalarOrVectorType(uint32_t id) const {
681 const Instruction* inst = FindDef(id);
682 assert(inst);
683
684 if (inst->opcode() == SpvOpTypeFloat) {
685 return true;
686 }
687
688 if (inst->opcode() == SpvOpTypeVector) {
689 return IsFloatScalarType(GetComponentType(id));
690 }
691
692 return false;
693 }
694
IsIntScalarType(uint32_t id) const695 bool ValidationState_t::IsIntScalarType(uint32_t id) const {
696 const Instruction* inst = FindDef(id);
697 assert(inst);
698 return inst->opcode() == SpvOpTypeInt;
699 }
700
IsIntVectorType(uint32_t id) const701 bool ValidationState_t::IsIntVectorType(uint32_t id) const {
702 const Instruction* inst = FindDef(id);
703 assert(inst);
704
705 if (inst->opcode() == SpvOpTypeVector) {
706 return IsIntScalarType(GetComponentType(id));
707 }
708
709 return false;
710 }
711
IsIntScalarOrVectorType(uint32_t id) const712 bool ValidationState_t::IsIntScalarOrVectorType(uint32_t id) const {
713 const Instruction* inst = FindDef(id);
714 assert(inst);
715
716 if (inst->opcode() == SpvOpTypeInt) {
717 return true;
718 }
719
720 if (inst->opcode() == SpvOpTypeVector) {
721 return IsIntScalarType(GetComponentType(id));
722 }
723
724 return false;
725 }
726
IsUnsignedIntScalarType(uint32_t id) const727 bool ValidationState_t::IsUnsignedIntScalarType(uint32_t id) const {
728 const Instruction* inst = FindDef(id);
729 assert(inst);
730 return inst->opcode() == SpvOpTypeInt && inst->word(3) == 0;
731 }
732
IsUnsignedIntVectorType(uint32_t id) const733 bool ValidationState_t::IsUnsignedIntVectorType(uint32_t id) const {
734 const Instruction* inst = FindDef(id);
735 assert(inst);
736
737 if (inst->opcode() == SpvOpTypeVector) {
738 return IsUnsignedIntScalarType(GetComponentType(id));
739 }
740
741 return false;
742 }
743
IsSignedIntScalarType(uint32_t id) const744 bool ValidationState_t::IsSignedIntScalarType(uint32_t id) const {
745 const Instruction* inst = FindDef(id);
746 assert(inst);
747 return inst->opcode() == SpvOpTypeInt && inst->word(3) == 1;
748 }
749
IsSignedIntVectorType(uint32_t id) const750 bool ValidationState_t::IsSignedIntVectorType(uint32_t id) const {
751 const Instruction* inst = FindDef(id);
752 assert(inst);
753
754 if (inst->opcode() == SpvOpTypeVector) {
755 return IsSignedIntScalarType(GetComponentType(id));
756 }
757
758 return false;
759 }
760
IsBoolScalarType(uint32_t id) const761 bool ValidationState_t::IsBoolScalarType(uint32_t id) const {
762 const Instruction* inst = FindDef(id);
763 assert(inst);
764 return inst->opcode() == SpvOpTypeBool;
765 }
766
IsBoolVectorType(uint32_t id) const767 bool ValidationState_t::IsBoolVectorType(uint32_t id) const {
768 const Instruction* inst = FindDef(id);
769 assert(inst);
770
771 if (inst->opcode() == SpvOpTypeVector) {
772 return IsBoolScalarType(GetComponentType(id));
773 }
774
775 return false;
776 }
777
IsBoolScalarOrVectorType(uint32_t id) const778 bool ValidationState_t::IsBoolScalarOrVectorType(uint32_t id) const {
779 const Instruction* inst = FindDef(id);
780 assert(inst);
781
782 if (inst->opcode() == SpvOpTypeBool) {
783 return true;
784 }
785
786 if (inst->opcode() == SpvOpTypeVector) {
787 return IsBoolScalarType(GetComponentType(id));
788 }
789
790 return false;
791 }
792
IsFloatMatrixType(uint32_t id) const793 bool ValidationState_t::IsFloatMatrixType(uint32_t id) const {
794 const Instruction* inst = FindDef(id);
795 assert(inst);
796
797 if (inst->opcode() == SpvOpTypeMatrix) {
798 return IsFloatScalarType(GetComponentType(id));
799 }
800
801 return false;
802 }
803
GetMatrixTypeInfo(uint32_t id,uint32_t * num_rows,uint32_t * num_cols,uint32_t * column_type,uint32_t * component_type) const804 bool ValidationState_t::GetMatrixTypeInfo(uint32_t id, uint32_t* num_rows,
805 uint32_t* num_cols,
806 uint32_t* column_type,
807 uint32_t* component_type) const {
808 if (!id) return false;
809
810 const Instruction* mat_inst = FindDef(id);
811 assert(mat_inst);
812 if (mat_inst->opcode() != SpvOpTypeMatrix) return false;
813
814 const uint32_t vec_type = mat_inst->word(2);
815 const Instruction* vec_inst = FindDef(vec_type);
816 assert(vec_inst);
817
818 if (vec_inst->opcode() != SpvOpTypeVector) {
819 assert(0);
820 return false;
821 }
822
823 *num_cols = mat_inst->word(3);
824 *num_rows = vec_inst->word(3);
825 *column_type = mat_inst->word(2);
826 *component_type = vec_inst->word(2);
827
828 return true;
829 }
830
GetStructMemberTypes(uint32_t struct_type_id,std::vector<uint32_t> * member_types) const831 bool ValidationState_t::GetStructMemberTypes(
832 uint32_t struct_type_id, std::vector<uint32_t>* member_types) const {
833 member_types->clear();
834 if (!struct_type_id) return false;
835
836 const Instruction* inst = FindDef(struct_type_id);
837 assert(inst);
838 if (inst->opcode() != SpvOpTypeStruct) return false;
839
840 *member_types =
841 std::vector<uint32_t>(inst->words().cbegin() + 2, inst->words().cend());
842
843 if (member_types->empty()) return false;
844
845 return true;
846 }
847
IsPointerType(uint32_t id) const848 bool ValidationState_t::IsPointerType(uint32_t id) const {
849 const Instruction* inst = FindDef(id);
850 assert(inst);
851 return inst->opcode() == SpvOpTypePointer;
852 }
853
GetPointerTypeInfo(uint32_t id,uint32_t * data_type,uint32_t * storage_class) const854 bool ValidationState_t::GetPointerTypeInfo(uint32_t id, uint32_t* data_type,
855 uint32_t* storage_class) const {
856 if (!id) return false;
857
858 const Instruction* inst = FindDef(id);
859 assert(inst);
860 if (inst->opcode() != SpvOpTypePointer) return false;
861
862 *storage_class = inst->word(2);
863 *data_type = inst->word(3);
864 return true;
865 }
866
IsCooperativeMatrixType(uint32_t id) const867 bool ValidationState_t::IsCooperativeMatrixType(uint32_t id) const {
868 const Instruction* inst = FindDef(id);
869 assert(inst);
870 return inst->opcode() == SpvOpTypeCooperativeMatrixNV;
871 }
872
IsFloatCooperativeMatrixType(uint32_t id) const873 bool ValidationState_t::IsFloatCooperativeMatrixType(uint32_t id) const {
874 if (!IsCooperativeMatrixType(id)) return false;
875 return IsFloatScalarType(FindDef(id)->word(2));
876 }
877
IsIntCooperativeMatrixType(uint32_t id) const878 bool ValidationState_t::IsIntCooperativeMatrixType(uint32_t id) const {
879 if (!IsCooperativeMatrixType(id)) return false;
880 return IsIntScalarType(FindDef(id)->word(2));
881 }
882
IsUnsignedIntCooperativeMatrixType(uint32_t id) const883 bool ValidationState_t::IsUnsignedIntCooperativeMatrixType(uint32_t id) const {
884 if (!IsCooperativeMatrixType(id)) return false;
885 return IsUnsignedIntScalarType(FindDef(id)->word(2));
886 }
887
CooperativeMatrixShapesMatch(const Instruction * inst,uint32_t m1,uint32_t m2)888 spv_result_t ValidationState_t::CooperativeMatrixShapesMatch(
889 const Instruction* inst, uint32_t m1, uint32_t m2) {
890 const auto m1_type = FindDef(m1);
891 const auto m2_type = FindDef(m2);
892
893 if (m1_type->opcode() != SpvOpTypeCooperativeMatrixNV ||
894 m2_type->opcode() != SpvOpTypeCooperativeMatrixNV) {
895 return diag(SPV_ERROR_INVALID_DATA, inst)
896 << "Expected cooperative matrix types";
897 }
898
899 uint32_t m1_scope_id = m1_type->GetOperandAs<uint32_t>(2);
900 uint32_t m1_rows_id = m1_type->GetOperandAs<uint32_t>(3);
901 uint32_t m1_cols_id = m1_type->GetOperandAs<uint32_t>(4);
902
903 uint32_t m2_scope_id = m2_type->GetOperandAs<uint32_t>(2);
904 uint32_t m2_rows_id = m2_type->GetOperandAs<uint32_t>(3);
905 uint32_t m2_cols_id = m2_type->GetOperandAs<uint32_t>(4);
906
907 bool m1_is_int32 = false, m1_is_const_int32 = false, m2_is_int32 = false,
908 m2_is_const_int32 = false;
909 uint32_t m1_value = 0, m2_value = 0;
910
911 std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
912 EvalInt32IfConst(m1_scope_id);
913 std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
914 EvalInt32IfConst(m2_scope_id);
915
916 if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
917 return diag(SPV_ERROR_INVALID_DATA, inst)
918 << "Expected scopes of Matrix and Result Type to be "
919 << "identical";
920 }
921
922 std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
923 EvalInt32IfConst(m1_rows_id);
924 std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
925 EvalInt32IfConst(m2_rows_id);
926
927 if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
928 return diag(SPV_ERROR_INVALID_DATA, inst)
929 << "Expected rows of Matrix type and Result Type to be "
930 << "identical";
931 }
932
933 std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
934 EvalInt32IfConst(m1_cols_id);
935 std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
936 EvalInt32IfConst(m2_cols_id);
937
938 if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
939 return diag(SPV_ERROR_INVALID_DATA, inst)
940 << "Expected columns of Matrix type and Result Type to be "
941 << "identical";
942 }
943
944 return SPV_SUCCESS;
945 }
946
GetOperandTypeId(const Instruction * inst,size_t operand_index) const947 uint32_t ValidationState_t::GetOperandTypeId(const Instruction* inst,
948 size_t operand_index) const {
949 return GetTypeId(inst->GetOperandAs<uint32_t>(operand_index));
950 }
951
GetConstantValUint64(uint32_t id,uint64_t * val) const952 bool ValidationState_t::GetConstantValUint64(uint32_t id, uint64_t* val) const {
953 const Instruction* inst = FindDef(id);
954 if (!inst) {
955 assert(0 && "Instruction not found");
956 return false;
957 }
958
959 if (inst->opcode() != SpvOpConstant && inst->opcode() != SpvOpSpecConstant)
960 return false;
961
962 if (!IsIntScalarType(inst->type_id())) return false;
963
964 if (inst->words().size() == 4) {
965 *val = inst->word(3);
966 } else {
967 assert(inst->words().size() == 5);
968 *val = inst->word(3);
969 *val |= uint64_t(inst->word(4)) << 32;
970 }
971 return true;
972 }
973
EvalInt32IfConst(uint32_t id) const974 std::tuple<bool, bool, uint32_t> ValidationState_t::EvalInt32IfConst(
975 uint32_t id) const {
976 const Instruction* const inst = FindDef(id);
977 assert(inst);
978 const uint32_t type = inst->type_id();
979
980 if (type == 0 || !IsIntScalarType(type) || GetBitWidth(type) != 32) {
981 return std::make_tuple(false, false, 0);
982 }
983
984 // Spec constant values cannot be evaluated so don't consider constant for
985 // the purpose of this method.
986 if (!spvOpcodeIsConstant(inst->opcode()) ||
987 spvOpcodeIsSpecConstant(inst->opcode())) {
988 return std::make_tuple(true, false, 0);
989 }
990
991 if (inst->opcode() == SpvOpConstantNull) {
992 return std::make_tuple(true, true, 0);
993 }
994
995 assert(inst->words().size() == 4);
996 return std::make_tuple(true, true, inst->word(3));
997 }
998
ComputeFunctionToEntryPointMapping()999 void ValidationState_t::ComputeFunctionToEntryPointMapping() {
1000 for (const uint32_t entry_point : entry_points()) {
1001 std::stack<uint32_t> call_stack;
1002 std::set<uint32_t> visited;
1003 call_stack.push(entry_point);
1004 while (!call_stack.empty()) {
1005 const uint32_t called_func_id = call_stack.top();
1006 call_stack.pop();
1007 if (!visited.insert(called_func_id).second) continue;
1008
1009 function_to_entry_points_[called_func_id].push_back(entry_point);
1010
1011 const Function* called_func = function(called_func_id);
1012 if (called_func) {
1013 // Other checks should error out on this invalid SPIR-V.
1014 for (const uint32_t new_call : called_func->function_call_targets()) {
1015 call_stack.push(new_call);
1016 }
1017 }
1018 }
1019 }
1020 }
1021
ComputeRecursiveEntryPoints()1022 void ValidationState_t::ComputeRecursiveEntryPoints() {
1023 for (const Function& func : functions()) {
1024 std::stack<uint32_t> call_stack;
1025 std::set<uint32_t> visited;
1026
1027 for (const uint32_t new_call : func.function_call_targets()) {
1028 call_stack.push(new_call);
1029 }
1030
1031 while (!call_stack.empty()) {
1032 const uint32_t called_func_id = call_stack.top();
1033 call_stack.pop();
1034
1035 if (!visited.insert(called_func_id).second) continue;
1036
1037 if (called_func_id == func.id()) {
1038 for (const uint32_t entry_point :
1039 function_to_entry_points_[called_func_id])
1040 recursive_entry_points_.insert(entry_point);
1041 break;
1042 }
1043
1044 const Function* called_func = function(called_func_id);
1045 if (called_func) {
1046 // Other checks should error out on this invalid SPIR-V.
1047 for (const uint32_t new_call : called_func->function_call_targets()) {
1048 call_stack.push(new_call);
1049 }
1050 }
1051 }
1052 }
1053 }
1054
FunctionEntryPoints(uint32_t func) const1055 const std::vector<uint32_t>& ValidationState_t::FunctionEntryPoints(
1056 uint32_t func) const {
1057 auto iter = function_to_entry_points_.find(func);
1058 if (iter == function_to_entry_points_.end()) {
1059 return empty_ids_;
1060 } else {
1061 return iter->second;
1062 }
1063 }
1064
EntryPointReferences(uint32_t id) const1065 std::set<uint32_t> ValidationState_t::EntryPointReferences(uint32_t id) const {
1066 std::set<uint32_t> referenced_entry_points;
1067 const auto inst = FindDef(id);
1068 if (!inst) return referenced_entry_points;
1069
1070 std::vector<const Instruction*> stack;
1071 stack.push_back(inst);
1072 while (!stack.empty()) {
1073 const auto current_inst = stack.back();
1074 stack.pop_back();
1075
1076 if (const auto func = current_inst->function()) {
1077 // Instruction lives in a function, we can stop searching.
1078 const auto function_entry_points = FunctionEntryPoints(func->id());
1079 referenced_entry_points.insert(function_entry_points.begin(),
1080 function_entry_points.end());
1081 } else {
1082 // Instruction is in the global scope, keep searching its uses.
1083 for (auto pair : current_inst->uses()) {
1084 const auto next_inst = pair.first;
1085 stack.push_back(next_inst);
1086 }
1087 }
1088 }
1089
1090 return referenced_entry_points;
1091 }
1092
Disassemble(const Instruction & inst) const1093 std::string ValidationState_t::Disassemble(const Instruction& inst) const {
1094 const spv_parsed_instruction_t& c_inst(inst.c_inst());
1095 return Disassemble(c_inst.words, c_inst.num_words);
1096 }
1097
Disassemble(const uint32_t * words,uint16_t num_words) const1098 std::string ValidationState_t::Disassemble(const uint32_t* words,
1099 uint16_t num_words) const {
1100 uint32_t disassembly_options = SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
1101 SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES;
1102
1103 return spvInstructionBinaryToText(context()->target_env, words, num_words,
1104 words_, num_words_, disassembly_options);
1105 }
1106
LogicallyMatch(const Instruction * lhs,const Instruction * rhs,bool check_decorations)1107 bool ValidationState_t::LogicallyMatch(const Instruction* lhs,
1108 const Instruction* rhs,
1109 bool check_decorations) {
1110 if (lhs->opcode() != rhs->opcode()) {
1111 return false;
1112 }
1113
1114 if (check_decorations) {
1115 const auto& dec_a = id_decorations(lhs->id());
1116 const auto& dec_b = id_decorations(rhs->id());
1117
1118 for (const auto& dec : dec_b) {
1119 if (std::find(dec_a.begin(), dec_a.end(), dec) == dec_a.end()) {
1120 return false;
1121 }
1122 }
1123 }
1124
1125 if (lhs->opcode() == SpvOpTypeArray) {
1126 // Size operands must match.
1127 if (lhs->GetOperandAs<uint32_t>(2u) != rhs->GetOperandAs<uint32_t>(2u)) {
1128 return false;
1129 }
1130
1131 // Elements must match or logically match.
1132 const auto lhs_ele_id = lhs->GetOperandAs<uint32_t>(1u);
1133 const auto rhs_ele_id = rhs->GetOperandAs<uint32_t>(1u);
1134 if (lhs_ele_id == rhs_ele_id) {
1135 return true;
1136 }
1137
1138 const auto lhs_ele = FindDef(lhs_ele_id);
1139 const auto rhs_ele = FindDef(rhs_ele_id);
1140 if (!lhs_ele || !rhs_ele) {
1141 return false;
1142 }
1143 return LogicallyMatch(lhs_ele, rhs_ele, check_decorations);
1144 } else if (lhs->opcode() == SpvOpTypeStruct) {
1145 // Number of elements must match.
1146 if (lhs->operands().size() != rhs->operands().size()) {
1147 return false;
1148 }
1149
1150 for (size_t i = 1u; i < lhs->operands().size(); ++i) {
1151 const auto lhs_ele_id = lhs->GetOperandAs<uint32_t>(i);
1152 const auto rhs_ele_id = rhs->GetOperandAs<uint32_t>(i);
1153 // Elements must match or logically match.
1154 if (lhs_ele_id == rhs_ele_id) {
1155 continue;
1156 }
1157
1158 const auto lhs_ele = FindDef(lhs_ele_id);
1159 const auto rhs_ele = FindDef(rhs_ele_id);
1160 if (!lhs_ele || !rhs_ele) {
1161 return false;
1162 }
1163
1164 if (!LogicallyMatch(lhs_ele, rhs_ele, check_decorations)) {
1165 return false;
1166 }
1167 }
1168
1169 // All checks passed.
1170 return true;
1171 }
1172
1173 // No other opcodes are acceptable at this point. Arrays and structs are
1174 // caught above and if they're elements are not arrays or structs they are
1175 // required to match exactly.
1176 return false;
1177 }
1178
TracePointer(const Instruction * inst) const1179 const Instruction* ValidationState_t::TracePointer(
1180 const Instruction* inst) const {
1181 auto base_ptr = inst;
1182 while (base_ptr->opcode() == SpvOpAccessChain ||
1183 base_ptr->opcode() == SpvOpInBoundsAccessChain ||
1184 base_ptr->opcode() == SpvOpPtrAccessChain ||
1185 base_ptr->opcode() == SpvOpInBoundsPtrAccessChain ||
1186 base_ptr->opcode() == SpvOpCopyObject) {
1187 base_ptr = FindDef(base_ptr->GetOperandAs<uint32_t>(2u));
1188 }
1189 return base_ptr;
1190 }
1191
ContainsSizedIntOrFloatType(uint32_t id,SpvOp type,uint32_t width) const1192 bool ValidationState_t::ContainsSizedIntOrFloatType(uint32_t id, SpvOp type,
1193 uint32_t width) const {
1194 if (type != SpvOpTypeInt && type != SpvOpTypeFloat) return false;
1195
1196 const auto inst = FindDef(id);
1197 if (!inst) return false;
1198
1199 if (inst->opcode() == type) {
1200 return inst->GetOperandAs<uint32_t>(1u) == width;
1201 }
1202
1203 switch (inst->opcode()) {
1204 case SpvOpTypeArray:
1205 case SpvOpTypeRuntimeArray:
1206 case SpvOpTypeVector:
1207 case SpvOpTypeMatrix:
1208 case SpvOpTypeImage:
1209 case SpvOpTypeSampledImage:
1210 case SpvOpTypeCooperativeMatrixNV:
1211 return ContainsSizedIntOrFloatType(inst->GetOperandAs<uint32_t>(1u), type,
1212 width);
1213 case SpvOpTypePointer:
1214 if (IsForwardPointer(id)) return false;
1215 return ContainsSizedIntOrFloatType(inst->GetOperandAs<uint32_t>(2u), type,
1216 width);
1217 case SpvOpTypeFunction:
1218 case SpvOpTypeStruct: {
1219 for (uint32_t i = 1; i < inst->operands().size(); ++i) {
1220 if (ContainsSizedIntOrFloatType(inst->GetOperandAs<uint32_t>(i), type,
1221 width))
1222 return true;
1223 }
1224 return false;
1225 }
1226 default:
1227 return false;
1228 }
1229 }
1230
ContainsLimitedUseIntOrFloatType(uint32_t id) const1231 bool ValidationState_t::ContainsLimitedUseIntOrFloatType(uint32_t id) const {
1232 if ((!HasCapability(SpvCapabilityInt16) &&
1233 ContainsSizedIntOrFloatType(id, SpvOpTypeInt, 16)) ||
1234 (!HasCapability(SpvCapabilityInt8) &&
1235 ContainsSizedIntOrFloatType(id, SpvOpTypeInt, 8)) ||
1236 (!HasCapability(SpvCapabilityFloat16) &&
1237 ContainsSizedIntOrFloatType(id, SpvOpTypeFloat, 16))) {
1238 return true;
1239 }
1240 return false;
1241 }
1242
IsValidStorageClass(SpvStorageClass storage_class) const1243 bool ValidationState_t::IsValidStorageClass(
1244 SpvStorageClass storage_class) const {
1245 if (spvIsVulkanEnv(context()->target_env)) {
1246 switch (storage_class) {
1247 case SpvStorageClassUniformConstant:
1248 case SpvStorageClassUniform:
1249 case SpvStorageClassStorageBuffer:
1250 case SpvStorageClassInput:
1251 case SpvStorageClassOutput:
1252 case SpvStorageClassImage:
1253 case SpvStorageClassWorkgroup:
1254 case SpvStorageClassPrivate:
1255 case SpvStorageClassFunction:
1256 case SpvStorageClassPushConstant:
1257 case SpvStorageClassPhysicalStorageBuffer:
1258 case SpvStorageClassRayPayloadNV:
1259 case SpvStorageClassIncomingRayPayloadNV:
1260 case SpvStorageClassHitAttributeNV:
1261 case SpvStorageClassCallableDataNV:
1262 case SpvStorageClassIncomingCallableDataNV:
1263 case SpvStorageClassShaderRecordBufferNV:
1264 return true;
1265 default:
1266 return false;
1267 }
1268 }
1269
1270 return true;
1271 }
1272
1273 #define VUID_WRAP(vuid) "[" #vuid "] "
1274
1275 // Currently no 2 VUID share the same id, so no need for |reference|
VkErrorID(uint32_t id,const char *) const1276 std::string ValidationState_t::VkErrorID(uint32_t id,
1277 const char* /*reference*/) const {
1278 if (!spvIsVulkanEnv(context_->target_env)) {
1279 return "";
1280 }
1281
1282 // This large switch case is only searched when an error has occured.
1283 // If an id is changed, the old case must be modified or removed. Each string
1284 // here is interpreted as being "implemented"
1285
1286 // Clang format adds spaces between hyphens
1287 // clang-format off
1288 switch (id) {
1289 case 4181:
1290 return VUID_WRAP(VUID-BaseInstance-BaseInstance-04181);
1291 case 4182:
1292 return VUID_WRAP(VUID-BaseInstance-BaseInstance-04182);
1293 case 4183:
1294 return VUID_WRAP(VUID-BaseInstance-BaseInstance-04183);
1295 case 4184:
1296 return VUID_WRAP(VUID-BaseVertex-BaseVertex-04184);
1297 case 4185:
1298 return VUID_WRAP(VUID-BaseVertex-BaseVertex-04185);
1299 case 4186:
1300 return VUID_WRAP(VUID-BaseVertex-BaseVertex-04186);
1301 case 4187:
1302 return VUID_WRAP(VUID-ClipDistance-ClipDistance-04187);
1303 case 4188:
1304 return VUID_WRAP(VUID-ClipDistance-ClipDistance-04188);
1305 case 4189:
1306 return VUID_WRAP(VUID-ClipDistance-ClipDistance-04189);
1307 case 4190:
1308 return VUID_WRAP(VUID-ClipDistance-ClipDistance-04190);
1309 case 4191:
1310 return VUID_WRAP(VUID-ClipDistance-ClipDistance-04191);
1311 case 4196:
1312 return VUID_WRAP(VUID-CullDistance-CullDistance-04196);
1313 case 4197:
1314 return VUID_WRAP(VUID-CullDistance-CullDistance-04197);
1315 case 4198:
1316 return VUID_WRAP(VUID-CullDistance-CullDistance-04198);
1317 case 4199:
1318 return VUID_WRAP(VUID-CullDistance-CullDistance-04199);
1319 case 4200:
1320 return VUID_WRAP(VUID-CullDistance-CullDistance-04200);
1321 case 4205:
1322 return VUID_WRAP(VUID-DeviceIndex-DeviceIndex-04205);
1323 case 4206:
1324 return VUID_WRAP(VUID-DeviceIndex-DeviceIndex-04206);
1325 case 4207:
1326 return VUID_WRAP(VUID-DrawIndex-DrawIndex-04207);
1327 case 4208:
1328 return VUID_WRAP(VUID-DrawIndex-DrawIndex-04208);
1329 case 4209:
1330 return VUID_WRAP(VUID-DrawIndex-DrawIndex-04209);
1331 case 4210:
1332 return VUID_WRAP(VUID-FragCoord-FragCoord-04210);
1333 case 4211:
1334 return VUID_WRAP(VUID-FragCoord-FragCoord-04211);
1335 case 4212:
1336 return VUID_WRAP(VUID-FragCoord-FragCoord-04212);
1337 case 4213:
1338 return VUID_WRAP(VUID-FragDepth-FragDepth-04213);
1339 case 4214:
1340 return VUID_WRAP(VUID-FragDepth-FragDepth-04214);
1341 case 4215:
1342 return VUID_WRAP(VUID-FragDepth-FragDepth-04215);
1343 case 4216:
1344 return VUID_WRAP(VUID-FragDepth-FragDepth-04216);
1345 case 4217:
1346 return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04217);
1347 case 4218:
1348 return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04218);
1349 case 4219:
1350 return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04219);
1351 case 4220:
1352 return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04220);
1353 case 4221:
1354 return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04221);
1355 case 4222:
1356 return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04222);
1357 case 4223:
1358 return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04223);
1359 case 4224:
1360 return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04224);
1361 case 4225:
1362 return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04225);
1363 case 4229:
1364 return VUID_WRAP(VUID-FrontFacing-FrontFacing-04229);
1365 case 4230:
1366 return VUID_WRAP(VUID-FrontFacing-FrontFacing-04230);
1367 case 4231:
1368 return VUID_WRAP(VUID-FrontFacing-FrontFacing-04231);
1369 case 4232:
1370 return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04232);
1371 case 4233:
1372 return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04233);
1373 case 4234:
1374 return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04234);
1375 case 4236:
1376 return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04236);
1377 case 4237:
1378 return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04237);
1379 case 4238:
1380 return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04238);
1381 case 4239:
1382 return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04239);
1383 case 4240:
1384 return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04240);
1385 case 4241:
1386 return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04241);
1387 case 4242:
1388 return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04242);
1389 case 4243:
1390 return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04243);
1391 case 4244:
1392 return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04244);
1393 case 4245:
1394 return VUID_WRAP(VUID-HitTNV-HitTNV-04245);
1395 case 4246:
1396 return VUID_WRAP(VUID-HitTNV-HitTNV-04246);
1397 case 4247:
1398 return VUID_WRAP(VUID-HitTNV-HitTNV-04247);
1399 case 4248:
1400 return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04248);
1401 case 4249:
1402 return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04249);
1403 case 4250:
1404 return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04250);
1405 case 4251:
1406 return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04251);
1407 case 4252:
1408 return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04252);
1409 case 4253:
1410 return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04253);
1411 case 4254:
1412 return VUID_WRAP(VUID-InstanceId-InstanceId-04254);
1413 case 4255:
1414 return VUID_WRAP(VUID-InstanceId-InstanceId-04255);
1415 case 4256:
1416 return VUID_WRAP(VUID-InstanceId-InstanceId-04256);
1417 case 4257:
1418 return VUID_WRAP(VUID-InvocationId-InvocationId-04257);
1419 case 4258:
1420 return VUID_WRAP(VUID-InvocationId-InvocationId-04258);
1421 case 4259:
1422 return VUID_WRAP(VUID-InvocationId-InvocationId-04259);
1423 case 4263:
1424 return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04263);
1425 case 4264:
1426 return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04264);
1427 case 4265:
1428 return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04265);
1429 case 4266:
1430 return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04266);
1431 case 4267:
1432 return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04267);
1433 case 4268:
1434 return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04268);
1435 case 4269:
1436 return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04269);
1437 case 4270:
1438 return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04270);
1439 case 4271:
1440 return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04271);
1441 case 4272:
1442 return VUID_WRAP(VUID-Layer-Layer-04272);
1443 case 4273:
1444 return VUID_WRAP(VUID-Layer-Layer-04273);
1445 case 4274:
1446 return VUID_WRAP(VUID-Layer-Layer-04274);
1447 case 4275:
1448 return VUID_WRAP(VUID-Layer-Layer-04275);
1449 case 4276:
1450 return VUID_WRAP(VUID-Layer-Layer-04276);
1451 case 4281:
1452 return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04281);
1453 case 4282:
1454 return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04282);
1455 case 4283:
1456 return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04283);
1457 case 4293:
1458 return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04293);
1459 case 4294:
1460 return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04294);
1461 case 4295:
1462 return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04295);
1463 case 4296:
1464 return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04296);
1465 case 4297:
1466 return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04297);
1467 case 4298:
1468 return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04298);
1469 case 4299:
1470 return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04299);
1471 case 4300:
1472 return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04300);
1473 case 4301:
1474 return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04301);
1475 case 4302:
1476 return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04302);
1477 case 4303:
1478 return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04303);
1479 case 4304:
1480 return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04304);
1481 case 4305:
1482 return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04305);
1483 case 4306:
1484 return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04306);
1485 case 4307:
1486 return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04307);
1487 case 4308:
1488 return VUID_WRAP(VUID-PatchVertices-PatchVertices-04308);
1489 case 4309:
1490 return VUID_WRAP(VUID-PatchVertices-PatchVertices-04309);
1491 case 4310:
1492 return VUID_WRAP(VUID-PatchVertices-PatchVertices-04310);
1493 case 4311:
1494 return VUID_WRAP(VUID-PointCoord-PointCoord-04311);
1495 case 4312:
1496 return VUID_WRAP(VUID-PointCoord-PointCoord-04312);
1497 case 4313:
1498 return VUID_WRAP(VUID-PointCoord-PointCoord-04313);
1499 case 4314:
1500 return VUID_WRAP(VUID-PointSize-PointSize-04314);
1501 case 4315:
1502 return VUID_WRAP(VUID-PointSize-PointSize-04315);
1503 case 4316:
1504 return VUID_WRAP(VUID-PointSize-PointSize-04316);
1505 case 4317:
1506 return VUID_WRAP(VUID-PointSize-PointSize-04317);
1507 case 4318:
1508 return VUID_WRAP(VUID-Position-Position-04318);
1509 case 4319:
1510 return VUID_WRAP(VUID-Position-Position-04319);
1511 case 4320:
1512 return VUID_WRAP(VUID-Position-Position-04320);
1513 case 4321:
1514 return VUID_WRAP(VUID-Position-Position-04321);
1515 case 4330:
1516 return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04330);
1517 case 4334:
1518 return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04334);
1519 case 4337:
1520 return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04337);
1521 case 4345:
1522 return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04345);
1523 case 4346:
1524 return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04346);
1525 case 4347:
1526 return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04347);
1527 case 4348:
1528 return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04348);
1529 case 4349:
1530 return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04349);
1531 case 4350:
1532 return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04350);
1533 case 4351:
1534 return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04351);
1535 case 4352:
1536 return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04352);
1537 case 4353:
1538 return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04353);
1539 case 4354:
1540 return VUID_WRAP(VUID-SampleId-SampleId-04354);
1541 case 4355:
1542 return VUID_WRAP(VUID-SampleId-SampleId-04355);
1543 case 4356:
1544 return VUID_WRAP(VUID-SampleId-SampleId-04356);
1545 case 4357:
1546 return VUID_WRAP(VUID-SampleMask-SampleMask-04357);
1547 case 4358:
1548 return VUID_WRAP(VUID-SampleMask-SampleMask-04358);
1549 case 4359:
1550 return VUID_WRAP(VUID-SampleMask-SampleMask-04359);
1551 case 4360:
1552 return VUID_WRAP(VUID-SamplePosition-SamplePosition-04360);
1553 case 4361:
1554 return VUID_WRAP(VUID-SamplePosition-SamplePosition-04361);
1555 case 4362:
1556 return VUID_WRAP(VUID-SamplePosition-SamplePosition-04362);
1557 case 4367:
1558 return VUID_WRAP(VUID-SubgroupId-SubgroupId-04367);
1559 case 4368:
1560 return VUID_WRAP(VUID-SubgroupId-SubgroupId-04368);
1561 case 4369:
1562 return VUID_WRAP(VUID-SubgroupId-SubgroupId-04369);
1563 case 4370:
1564 return VUID_WRAP(VUID-SubgroupEqMask-SubgroupEqMask-04370);
1565 case 4371:
1566 return VUID_WRAP(VUID-SubgroupEqMask-SubgroupEqMask-04371);
1567 case 4372:
1568 return VUID_WRAP(VUID-SubgroupGeMask-SubgroupGeMask-04372);
1569 case 4373:
1570 return VUID_WRAP(VUID-SubgroupGeMask-SubgroupGeMask-04373);
1571 case 4374:
1572 return VUID_WRAP(VUID-SubgroupGtMask-SubgroupGtMask-04374);
1573 case 4375:
1574 return VUID_WRAP(VUID-SubgroupGtMask-SubgroupGtMask-04375);
1575 case 4376:
1576 return VUID_WRAP(VUID-SubgroupLeMask-SubgroupLeMask-04376);
1577 case 4377:
1578 return VUID_WRAP(VUID-SubgroupLeMask-SubgroupLeMask-04377);
1579 case 4378:
1580 return VUID_WRAP(VUID-SubgroupLtMask-SubgroupLtMask-04378);
1581 case 4379:
1582 return VUID_WRAP(VUID-SubgroupLtMask-SubgroupLtMask-04379);
1583 case 4380:
1584 return VUID_WRAP(VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-04380);
1585 case 4381:
1586 return VUID_WRAP(VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-04381);
1587 case 4382:
1588 return VUID_WRAP(VUID-SubgroupSize-SubgroupSize-04382);
1589 case 4383:
1590 return VUID_WRAP(VUID-SubgroupSize-SubgroupSize-04383);
1591 case 4387:
1592 return VUID_WRAP(VUID-TessCoord-TessCoord-04387);
1593 case 4388:
1594 return VUID_WRAP(VUID-TessCoord-TessCoord-04388);
1595 case 4389:
1596 return VUID_WRAP(VUID-TessCoord-TessCoord-04389);
1597 case 4390:
1598 return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04390);
1599 case 4391:
1600 return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04391);
1601 case 4392:
1602 return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04392);
1603 case 4393:
1604 return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04393);
1605 case 4394:
1606 return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04394);
1607 case 4395:
1608 return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04395);
1609 case 4396:
1610 return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04396);
1611 case 4397:
1612 return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04397);
1613 case 4398:
1614 return VUID_WRAP(VUID-VertexIndex-VertexIndex-04398);
1615 case 4399:
1616 return VUID_WRAP(VUID-VertexIndex-VertexIndex-04399);
1617 case 4400:
1618 return VUID_WRAP(VUID-VertexIndex-VertexIndex-04400);
1619 case 4401:
1620 return VUID_WRAP(VUID-ViewIndex-ViewIndex-04401);
1621 case 4402:
1622 return VUID_WRAP(VUID-ViewIndex-ViewIndex-04402);
1623 case 4403:
1624 return VUID_WRAP(VUID-ViewIndex-ViewIndex-04403);
1625 case 4404:
1626 return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04404);
1627 case 4405:
1628 return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04405);
1629 case 4406:
1630 return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04406);
1631 case 4407:
1632 return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04407);
1633 case 4408:
1634 return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04408);
1635 case 4422:
1636 return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04422);
1637 case 4423:
1638 return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04423);
1639 case 4424:
1640 return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04424);
1641 case 4425:
1642 return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04425);
1643 case 4426:
1644 return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04426);
1645 case 4427:
1646 return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04427);
1647 case 4428:
1648 return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04428);
1649 case 4429:
1650 return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04429);
1651 case 4430:
1652 return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04430);
1653 case 4431:
1654 return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04431);
1655 case 4432:
1656 return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04432);
1657 case 4433:
1658 return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04433);
1659 case 4434:
1660 return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04434);
1661 case 4435:
1662 return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04435);
1663 case 4436:
1664 return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04436);
1665 case 4484:
1666 return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04484);
1667 case 4485:
1668 return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04485);
1669 case 4486:
1670 return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04486);
1671 case 4490:
1672 return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04490);
1673 case 4491:
1674 return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04491);
1675 case 4492:
1676 return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04492);
1677 case 4633:
1678 return VUID_WRAP(VUID-StandaloneSpirv-None-04633);
1679 case 4635:
1680 return VUID_WRAP(VUID-StandaloneSpirv-None-04635);
1681 case 4638:
1682 return VUID_WRAP(VUID-StandaloneSpirv-None-04638);
1683 case 4639:
1684 return VUID_WRAP(VUID-StandaloneSpirv-None-04639);
1685 case 4640:
1686 return VUID_WRAP(VUID-StandaloneSpirv-None-04640);
1687 case 4642:
1688 return VUID_WRAP(VUID-StandaloneSpirv-None-04642);
1689 case 4651:
1690 return VUID_WRAP(VUID-StandaloneSpirv-OpVariable-04651);
1691 case 4652:
1692 return VUID_WRAP(VUID-StandaloneSpirv-OpReadClockKHR-04652);
1693 case 4653:
1694 return VUID_WRAP(VUID-StandaloneSpirv-OriginLowerLeft-04653);
1695 case 4654:
1696 return VUID_WRAP(VUID-StandaloneSpirv-PixelCenterInteger-04654);
1697 case 4656:
1698 return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-04656);
1699 case 4657:
1700 return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-04657);
1701 case 4658:
1702 return VUID_WRAP(VUID-StandaloneSpirv-OpImageTexelPointer-04658);
1703 case 4659:
1704 return VUID_WRAP(VUID-StandaloneSpirv-OpImageQuerySizeLod-04659);
1705 case 4662:
1706 return VUID_WRAP(VUID-StandaloneSpirv-Offset-04662);
1707 case 4663:
1708 return VUID_WRAP(VUID-StandaloneSpirv-Offset-04663);
1709 case 4669:
1710 return VUID_WRAP(VUID-StandaloneSpirv-GLSLShared-04669);
1711 case 4675:
1712 return VUID_WRAP(VUID-StandaloneSpirv-FPRoundingMode-04675);
1713 case 4677:
1714 return VUID_WRAP(VUID-StandaloneSpirv-Invariant-04677);
1715 case 4683:
1716 return VUID_WRAP(VUID-StandaloneSpirv-LocalSize-04683);
1717 case 4685:
1718 return VUID_WRAP(VUID-StandaloneSpirv-OpGroupNonUniformBallotBitCount-04685);
1719 case 4686:
1720 return VUID_WRAP(VUID-StandaloneSpirv-None-04686);
1721 case 4710:
1722 return VUID_WRAP(VUID-StandaloneSpirv-PhysicalStorageBuffer64-04710);
1723 case 4711:
1724 return VUID_WRAP(VUID-StandaloneSpirv-OpTypeForwardPointer-04711);
1725 case 4730:
1726 return VUID_WRAP(VUID-StandaloneSpirv-OpAtomicStore-04730);
1727 case 4731:
1728 return VUID_WRAP(VUID-StandaloneSpirv-OpAtomicLoad-04731);
1729 case 4732:
1730 return VUID_WRAP(VUID-StandaloneSpirv-OpMemoryBarrier-04732);
1731 case 4733:
1732 return VUID_WRAP(VUID-StandaloneSpirv-OpMemoryBarrier-04733);
1733 default:
1734 return ""; // unknown id
1735 };
1736 // clang-format on
1737 }
1738
1739 } // namespace val
1740 } // namespace spvtools
1741