• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     case SpvOpSamplerImageAddressingModeNV:
94       return kLayoutSamplerImageAddressMode;
95     default:
96       break;
97   }
98   return kLayoutFunctionDefinitions;
99 }
100 
IsInstructionInLayoutSection(ModuleLayoutSection layout,SpvOp op)101 bool IsInstructionInLayoutSection(ModuleLayoutSection layout, SpvOp op) {
102   return layout == InstructionLayoutSection(layout, op);
103 }
104 
105 // Counts the number of instructions and functions in the file.
CountInstructions(void * user_data,const spv_parsed_instruction_t * inst)106 spv_result_t CountInstructions(void* user_data,
107                                const spv_parsed_instruction_t* inst) {
108   ValidationState_t& _ = *(reinterpret_cast<ValidationState_t*>(user_data));
109   if (inst->opcode == SpvOpFunction) _.increment_total_functions();
110   _.increment_total_instructions();
111 
112   return SPV_SUCCESS;
113 }
114 
setHeader(void * user_data,spv_endianness_t,uint32_t,uint32_t version,uint32_t generator,uint32_t id_bound,uint32_t)115 spv_result_t setHeader(void* user_data, spv_endianness_t, uint32_t,
116                        uint32_t version, uint32_t generator, uint32_t id_bound,
117                        uint32_t) {
118   ValidationState_t& vstate =
119       *(reinterpret_cast<ValidationState_t*>(user_data));
120   vstate.setIdBound(id_bound);
121   vstate.setGenerator(generator);
122   vstate.setVersion(version);
123 
124   return SPV_SUCCESS;
125 }
126 
127 // Add features based on SPIR-V core version number.
UpdateFeaturesBasedOnSpirvVersion(ValidationState_t::Feature * features,uint32_t version)128 void UpdateFeaturesBasedOnSpirvVersion(ValidationState_t::Feature* features,
129                                        uint32_t version) {
130   assert(features);
131   if (version >= SPV_SPIRV_VERSION_WORD(1, 4)) {
132     features->select_between_composites = true;
133     features->copy_memory_permits_two_memory_accesses = true;
134     features->uconvert_spec_constant_op = true;
135     features->nonwritable_var_in_function_or_private = true;
136   }
137 }
138 
139 }  // namespace
140 
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)141 ValidationState_t::ValidationState_t(const spv_const_context ctx,
142                                      const spv_const_validator_options opt,
143                                      const uint32_t* words,
144                                      const size_t num_words,
145                                      const uint32_t max_warnings)
146     : context_(ctx),
147       options_(opt),
148       words_(words),
149       num_words_(num_words),
150       unresolved_forward_ids_{},
151       operand_names_{},
152       current_layout_section_(kLayoutCapabilities),
153       module_functions_(),
154       module_capabilities_(),
155       module_extensions_(),
156       ordered_instructions_(),
157       all_definitions_(),
158       global_vars_(),
159       local_vars_(),
160       struct_nesting_depth_(),
161       struct_has_nested_blockorbufferblock_struct_(),
162       grammar_(ctx),
163       addressing_model_(SpvAddressingModelMax),
164       memory_model_(SpvMemoryModelMax),
165       pointer_size_and_alignment_(0),
166       sampler_image_addressing_mode_(0),
167       in_function_(false),
168       num_of_warnings_(0),
169       max_num_of_warnings_(max_warnings) {
170   assert(opt && "Validator options may not be Null.");
171 
172   const auto env = context_->target_env;
173 
174   if (spvIsVulkanEnv(env)) {
175     // Vulkan 1.1 includes VK_KHR_relaxed_block_layout in core.
176     if (env != SPV_ENV_VULKAN_1_0) {
177       features_.env_relaxed_block_layout = true;
178     }
179   }
180 
181   // LocalSizeId is only disallowed prior to Vulkan 1.3 without maintenance4.
182   switch (env) {
183     case SPV_ENV_VULKAN_1_0:
184     case SPV_ENV_VULKAN_1_1:
185     case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
186     case SPV_ENV_VULKAN_1_2:
187       features_.env_allow_localsizeid = false;
188       break;
189     default:
190       features_.env_allow_localsizeid = true;
191       break;
192   }
193 
194   // Only attempt to count if we have words, otherwise let the other validation
195   // fail and generate an error.
196   if (num_words > 0) {
197     // Count the number of instructions in the binary.
198     // This parse should not produce any error messages. Hijack the context and
199     // replace the message consumer so that we do not pollute any state in input
200     // consumer.
201     spv_context_t hijacked_context = *ctx;
202     hijacked_context.consumer = [](spv_message_level_t, const char*,
__anon0d43d9700202(spv_message_level_t, const char*, const spv_position_t&, const char*) 203                                    const spv_position_t&, const char*) {};
204     spvBinaryParse(&hijacked_context, this, words, num_words, setHeader,
205                    CountInstructions,
206                    /* diagnostic = */ nullptr);
207     preallocateStorage();
208   }
209   UpdateFeaturesBasedOnSpirvVersion(&features_, version_);
210 
211   name_mapper_ = spvtools::GetTrivialNameMapper();
212   if (options_->use_friendly_names) {
213     friendly_mapper_ = spvtools::MakeUnique<spvtools::FriendlyNameMapper>(
214         context_, words_, num_words_);
215     name_mapper_ = friendly_mapper_->GetNameMapper();
216   }
217 }
218 
preallocateStorage()219 void ValidationState_t::preallocateStorage() {
220   ordered_instructions_.reserve(total_instructions_);
221   module_functions_.reserve(total_functions_);
222 }
223 
ForwardDeclareId(uint32_t id)224 spv_result_t ValidationState_t::ForwardDeclareId(uint32_t id) {
225   unresolved_forward_ids_.insert(id);
226   return SPV_SUCCESS;
227 }
228 
RemoveIfForwardDeclared(uint32_t id)229 spv_result_t ValidationState_t::RemoveIfForwardDeclared(uint32_t id) {
230   unresolved_forward_ids_.erase(id);
231   return SPV_SUCCESS;
232 }
233 
RegisterForwardPointer(uint32_t id)234 spv_result_t ValidationState_t::RegisterForwardPointer(uint32_t id) {
235   forward_pointer_ids_.insert(id);
236   return SPV_SUCCESS;
237 }
238 
IsForwardPointer(uint32_t id) const239 bool ValidationState_t::IsForwardPointer(uint32_t id) const {
240   return (forward_pointer_ids_.find(id) != forward_pointer_ids_.end());
241 }
242 
AssignNameToId(uint32_t id,std::string name)243 void ValidationState_t::AssignNameToId(uint32_t id, std::string name) {
244   operand_names_[id] = name;
245 }
246 
getIdName(uint32_t id) const247 std::string ValidationState_t::getIdName(uint32_t id) const {
248   const std::string id_name = name_mapper_(id);
249 
250   std::stringstream out;
251   out << "'" << id << "[%" << id_name << "]'";
252   return out.str();
253 }
254 
unresolved_forward_id_count() const255 size_t ValidationState_t::unresolved_forward_id_count() const {
256   return unresolved_forward_ids_.size();
257 }
258 
UnresolvedForwardIds() const259 std::vector<uint32_t> ValidationState_t::UnresolvedForwardIds() const {
260   std::vector<uint32_t> out(std::begin(unresolved_forward_ids_),
261                             std::end(unresolved_forward_ids_));
262   return out;
263 }
264 
IsDefinedId(uint32_t id) const265 bool ValidationState_t::IsDefinedId(uint32_t id) const {
266   return all_definitions_.find(id) != std::end(all_definitions_);
267 }
268 
FindDef(uint32_t id) const269 const Instruction* ValidationState_t::FindDef(uint32_t id) const {
270   auto it = all_definitions_.find(id);
271   if (it == all_definitions_.end()) return nullptr;
272   return it->second;
273 }
274 
FindDef(uint32_t id)275 Instruction* ValidationState_t::FindDef(uint32_t id) {
276   auto it = all_definitions_.find(id);
277   if (it == all_definitions_.end()) return nullptr;
278   return it->second;
279 }
280 
current_layout_section() const281 ModuleLayoutSection ValidationState_t::current_layout_section() const {
282   return current_layout_section_;
283 }
284 
ProgressToNextLayoutSectionOrder()285 void ValidationState_t::ProgressToNextLayoutSectionOrder() {
286   // Guard against going past the last element(kLayoutFunctionDefinitions)
287   if (current_layout_section_ <= kLayoutFunctionDefinitions) {
288     current_layout_section_ =
289         static_cast<ModuleLayoutSection>(current_layout_section_ + 1);
290   }
291 }
292 
IsOpcodeInPreviousLayoutSection(SpvOp op)293 bool ValidationState_t::IsOpcodeInPreviousLayoutSection(SpvOp op) {
294   ModuleLayoutSection section =
295       InstructionLayoutSection(current_layout_section_, op);
296   return section < current_layout_section_;
297 }
298 
IsOpcodeInCurrentLayoutSection(SpvOp op)299 bool ValidationState_t::IsOpcodeInCurrentLayoutSection(SpvOp op) {
300   return IsInstructionInLayoutSection(current_layout_section_, op);
301 }
302 
diag(spv_result_t error_code,const Instruction * inst)303 DiagnosticStream ValidationState_t::diag(spv_result_t error_code,
304                                          const Instruction* inst) {
305   if (error_code == SPV_WARNING) {
306     if (num_of_warnings_ == max_num_of_warnings_) {
307       DiagnosticStream({0, 0, 0}, context_->consumer, "", error_code)
308           << "Other warnings have been suppressed.\n";
309     }
310     if (num_of_warnings_ >= max_num_of_warnings_) {
311       return DiagnosticStream({0, 0, 0}, nullptr, "", error_code);
312     }
313     ++num_of_warnings_;
314   }
315 
316   std::string disassembly;
317   if (inst) disassembly = Disassemble(*inst);
318 
319   return DiagnosticStream({0, 0, inst ? inst->LineNum() : 0},
320                           context_->consumer, disassembly, error_code);
321 }
322 
functions()323 std::vector<Function>& ValidationState_t::functions() {
324   return module_functions_;
325 }
326 
current_function()327 Function& ValidationState_t::current_function() {
328   assert(in_function_body());
329   return module_functions_.back();
330 }
331 
current_function() const332 const Function& ValidationState_t::current_function() const {
333   assert(in_function_body());
334   return module_functions_.back();
335 }
336 
function(uint32_t id) const337 const Function* ValidationState_t::function(uint32_t id) const {
338   const auto it = id_to_function_.find(id);
339   if (it == id_to_function_.end()) return nullptr;
340   return it->second;
341 }
342 
function(uint32_t id)343 Function* ValidationState_t::function(uint32_t id) {
344   auto it = id_to_function_.find(id);
345   if (it == id_to_function_.end()) return nullptr;
346   return it->second;
347 }
348 
in_function_body() const349 bool ValidationState_t::in_function_body() const { return in_function_; }
350 
in_block() const351 bool ValidationState_t::in_block() const {
352   return module_functions_.empty() == false &&
353          module_functions_.back().current_block() != nullptr;
354 }
355 
RegisterCapability(SpvCapability cap)356 void ValidationState_t::RegisterCapability(SpvCapability cap) {
357   // Avoid redundant work.  Otherwise the recursion could induce work
358   // quadrdatic in the capability dependency depth. (Ok, not much, but
359   // it's something.)
360   if (module_capabilities_.Contains(cap)) return;
361 
362   module_capabilities_.Add(cap);
363   spv_operand_desc desc;
364   if (SPV_SUCCESS ==
365       grammar_.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY, cap, &desc)) {
366     CapabilitySet(desc->numCapabilities, desc->capabilities)
367         .ForEach([this](SpvCapability c) { RegisterCapability(c); });
368   }
369 
370   switch (cap) {
371     case SpvCapabilityKernel:
372       features_.group_ops_reduce_and_scans = true;
373       break;
374     case SpvCapabilityInt8:
375       features_.use_int8_type = true;
376       features_.declare_int8_type = true;
377       break;
378     case SpvCapabilityStorageBuffer8BitAccess:
379     case SpvCapabilityUniformAndStorageBuffer8BitAccess:
380     case SpvCapabilityStoragePushConstant8:
381     case SpvCapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR:
382       features_.declare_int8_type = true;
383       break;
384     case SpvCapabilityInt16:
385       features_.declare_int16_type = true;
386       break;
387     case SpvCapabilityFloat16:
388     case SpvCapabilityFloat16Buffer:
389       features_.declare_float16_type = true;
390       break;
391     case SpvCapabilityStorageUniformBufferBlock16:
392     case SpvCapabilityStorageUniform16:
393     case SpvCapabilityStoragePushConstant16:
394     case SpvCapabilityStorageInputOutput16:
395     case SpvCapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR:
396       features_.declare_int16_type = true;
397       features_.declare_float16_type = true;
398       features_.free_fp_rounding_mode = true;
399       break;
400     case SpvCapabilityVariablePointers:
401     case SpvCapabilityVariablePointersStorageBuffer:
402       features_.variable_pointers = true;
403       break;
404     default:
405       // TODO(dneto): For now don't validate SPV_NV_ray_tracing, which uses
406       // capability SpvCapabilityRayTracingNV.
407       // SpvCapabilityRayTracingProvisionalKHR would need the same treatment.
408       // One of the differences going from SPV_KHR_ray_tracing from
409       // provisional to final spec was the provisional spec uses Locations
410       // for variables in certain storage classes, just like the
411       // SPV_NV_ray_tracing extension.  So it mimics the NVIDIA extension.
412       // The final SPV_KHR_ray_tracing uses a different capability token
413       // number, so it doesn't fall into this case.
414       break;
415   }
416 }
417 
RegisterExtension(Extension ext)418 void ValidationState_t::RegisterExtension(Extension ext) {
419   if (module_extensions_.Contains(ext)) return;
420 
421   module_extensions_.Add(ext);
422 
423   switch (ext) {
424     case kSPV_AMD_gpu_shader_half_float:
425     case kSPV_AMD_gpu_shader_half_float_fetch:
426       // SPV_AMD_gpu_shader_half_float enables float16 type.
427       // https://github.com/KhronosGroup/SPIRV-Tools/issues/1375
428       features_.declare_float16_type = true;
429       break;
430     case kSPV_AMD_gpu_shader_int16:
431       // This is not yet in the extension, but it's recommended for it.
432       // See https://github.com/KhronosGroup/glslang/issues/848
433       features_.uconvert_spec_constant_op = true;
434       break;
435     case kSPV_AMD_shader_ballot:
436       // The grammar doesn't encode the fact that SPV_AMD_shader_ballot
437       // enables the use of group operations Reduce, InclusiveScan,
438       // and ExclusiveScan.  Enable it manually.
439       // https://github.com/KhronosGroup/SPIRV-Tools/issues/991
440       features_.group_ops_reduce_and_scans = true;
441       break;
442     default:
443       break;
444   }
445 }
446 
HasAnyOfCapabilities(const CapabilitySet & capabilities) const447 bool ValidationState_t::HasAnyOfCapabilities(
448     const CapabilitySet& capabilities) const {
449   return module_capabilities_.HasAnyOf(capabilities);
450 }
451 
HasAnyOfExtensions(const ExtensionSet & extensions) const452 bool ValidationState_t::HasAnyOfExtensions(
453     const ExtensionSet& extensions) const {
454   return module_extensions_.HasAnyOf(extensions);
455 }
456 
set_addressing_model(SpvAddressingModel am)457 void ValidationState_t::set_addressing_model(SpvAddressingModel am) {
458   addressing_model_ = am;
459   switch (am) {
460     case SpvAddressingModelPhysical32:
461       pointer_size_and_alignment_ = 4;
462       break;
463     default:
464     // fall through
465     case SpvAddressingModelPhysical64:
466     case SpvAddressingModelPhysicalStorageBuffer64:
467       pointer_size_and_alignment_ = 8;
468       break;
469   }
470 }
471 
addressing_model() const472 SpvAddressingModel ValidationState_t::addressing_model() const {
473   return addressing_model_;
474 }
475 
set_memory_model(SpvMemoryModel mm)476 void ValidationState_t::set_memory_model(SpvMemoryModel mm) {
477   memory_model_ = mm;
478 }
479 
memory_model() const480 SpvMemoryModel ValidationState_t::memory_model() const { return memory_model_; }
481 
set_samplerimage_variable_address_mode(uint32_t bit_width)482 void ValidationState_t::set_samplerimage_variable_address_mode(
483     uint32_t bit_width) {
484   sampler_image_addressing_mode_ = bit_width;
485 }
486 
samplerimage_variable_address_mode() const487 uint32_t ValidationState_t::samplerimage_variable_address_mode() const {
488   return sampler_image_addressing_mode_;
489 }
490 
RegisterFunction(uint32_t id,uint32_t ret_type_id,SpvFunctionControlMask function_control,uint32_t function_type_id)491 spv_result_t ValidationState_t::RegisterFunction(
492     uint32_t id, uint32_t ret_type_id, SpvFunctionControlMask function_control,
493     uint32_t function_type_id) {
494   assert(in_function_body() == false &&
495          "RegisterFunction can only be called when parsing the binary outside "
496          "of another function");
497   in_function_ = true;
498   module_functions_.emplace_back(id, ret_type_id, function_control,
499                                  function_type_id);
500   id_to_function_.emplace(id, &current_function());
501 
502   // TODO(umar): validate function type and type_id
503 
504   return SPV_SUCCESS;
505 }
506 
RegisterFunctionEnd()507 spv_result_t ValidationState_t::RegisterFunctionEnd() {
508   assert(in_function_body() == true &&
509          "RegisterFunctionEnd can only be called when parsing the binary "
510          "inside of another function");
511   assert(in_block() == false &&
512          "RegisterFunctionParameter can only be called when parsing the binary "
513          "outside of a block");
514   current_function().RegisterFunctionEnd();
515   in_function_ = false;
516   return SPV_SUCCESS;
517 }
518 
AddOrderedInstruction(const spv_parsed_instruction_t * inst)519 Instruction* ValidationState_t::AddOrderedInstruction(
520     const spv_parsed_instruction_t* inst) {
521   ordered_instructions_.emplace_back(inst);
522   ordered_instructions_.back().SetLineNum(ordered_instructions_.size());
523   return &ordered_instructions_.back();
524 }
525 
526 // Improves diagnostic messages by collecting names of IDs
RegisterDebugInstruction(const Instruction * inst)527 void ValidationState_t::RegisterDebugInstruction(const Instruction* inst) {
528   switch (inst->opcode()) {
529     case SpvOpName: {
530       const auto target = inst->GetOperandAs<uint32_t>(0);
531       const std::string str = inst->GetOperandAs<std::string>(1);
532       AssignNameToId(target, str);
533       break;
534     }
535     case SpvOpMemberName: {
536       const auto target = inst->GetOperandAs<uint32_t>(0);
537       const std::string str = inst->GetOperandAs<std::string>(2);
538       AssignNameToId(target, str);
539       break;
540     }
541     case SpvOpSourceContinued:
542     case SpvOpSource:
543     case SpvOpSourceExtension:
544     case SpvOpString:
545     case SpvOpLine:
546     case SpvOpNoLine:
547     default:
548       break;
549   }
550 }
551 
RegisterInstruction(Instruction * inst)552 void ValidationState_t::RegisterInstruction(Instruction* inst) {
553   if (inst->id()) all_definitions_.insert(std::make_pair(inst->id(), inst));
554 
555   // Some validation checks are easier by getting all the consumers
556   for (size_t i = 0; i < inst->operands().size(); ++i) {
557     const spv_parsed_operand_t& operand = inst->operand(i);
558     if ((SPV_OPERAND_TYPE_ID == operand.type) ||
559         (SPV_OPERAND_TYPE_TYPE_ID == operand.type)) {
560       const uint32_t operand_word = inst->word(operand.offset);
561       Instruction* operand_inst = FindDef(operand_word);
562       if (!operand_inst) {
563         continue;
564       }
565 
566       // If the instruction is using an OpTypeSampledImage as an operand, it
567       // should be recorded. The validator will ensure that all usages of an
568       // OpTypeSampledImage and its definition are in the same basic block.
569       if ((SPV_OPERAND_TYPE_ID == operand.type) &&
570           (SpvOpSampledImage == operand_inst->opcode())) {
571         RegisterSampledImageConsumer(operand_word, inst);
572       }
573 
574       // In order to track storage classes (not Function) used per execution
575       // model we can't use RegisterExecutionModelLimitation on instructions
576       // like OpTypePointer which are going to be in the pre-function section.
577       // Instead just need to register storage class usage for consumers in a
578       // function block.
579       if (inst->function()) {
580         if (operand_inst->opcode() == SpvOpTypePointer) {
581           RegisterStorageClassConsumer(
582               operand_inst->GetOperandAs<SpvStorageClass>(1), inst);
583         } else if (operand_inst->opcode() == SpvOpVariable) {
584           RegisterStorageClassConsumer(
585               operand_inst->GetOperandAs<SpvStorageClass>(2), inst);
586         }
587       }
588     }
589   }
590 }
591 
getSampledImageConsumers(uint32_t sampled_image_id) const592 std::vector<Instruction*> ValidationState_t::getSampledImageConsumers(
593     uint32_t sampled_image_id) const {
594   std::vector<Instruction*> result;
595   auto iter = sampled_image_consumers_.find(sampled_image_id);
596   if (iter != sampled_image_consumers_.end()) {
597     result = iter->second;
598   }
599   return result;
600 }
601 
RegisterSampledImageConsumer(uint32_t sampled_image_id,Instruction * consumer)602 void ValidationState_t::RegisterSampledImageConsumer(uint32_t sampled_image_id,
603                                                      Instruction* consumer) {
604   sampled_image_consumers_[sampled_image_id].push_back(consumer);
605 }
606 
RegisterStorageClassConsumer(SpvStorageClass storage_class,Instruction * consumer)607 void ValidationState_t::RegisterStorageClassConsumer(
608     SpvStorageClass storage_class, Instruction* consumer) {
609   if (spvIsVulkanEnv(context()->target_env)) {
610     if (storage_class == SpvStorageClassOutput) {
611       std::string errorVUID = VkErrorID(4644);
612       function(consumer->function()->id())
613           ->RegisterExecutionModelLimitation([errorVUID](
614                                                  SpvExecutionModel model,
615                                                  std::string* message) {
616             if (model == SpvExecutionModelGLCompute ||
617                 model == SpvExecutionModelRayGenerationKHR ||
618                 model == SpvExecutionModelIntersectionKHR ||
619                 model == SpvExecutionModelAnyHitKHR ||
620                 model == SpvExecutionModelClosestHitKHR ||
621                 model == SpvExecutionModelMissKHR ||
622                 model == SpvExecutionModelCallableKHR) {
623               if (message) {
624                 *message =
625                     errorVUID +
626                     "in Vulkan environment, Output Storage Class must not be "
627                     "used in GLCompute, RayGenerationKHR, IntersectionKHR, "
628                     "AnyHitKHR, ClosestHitKHR, MissKHR, or CallableKHR "
629                     "execution models";
630               }
631               return false;
632             }
633             return true;
634           });
635     }
636 
637     if (storage_class == SpvStorageClassWorkgroup) {
638       std::string errorVUID = VkErrorID(4645);
639       function(consumer->function()->id())
640           ->RegisterExecutionModelLimitation([errorVUID](
641                                                  SpvExecutionModel model,
642                                                  std::string* message) {
643             if (model != SpvExecutionModelGLCompute &&
644                 model != SpvExecutionModelTaskNV &&
645                 model != SpvExecutionModelMeshNV &&
646                 model != SpvExecutionModelTaskEXT &&
647                 model != SpvExecutionModelMeshEXT) {
648               if (message) {
649                 *message =
650                     errorVUID +
651                     "in Vulkan environment, Workgroup Storage Class is limited "
652                     "to MeshNV, TaskNV, and GLCompute execution model";
653               }
654               return false;
655             }
656             return true;
657           });
658     }
659   }
660 
661   if (storage_class == SpvStorageClassCallableDataKHR) {
662     std::string errorVUID = VkErrorID(4704);
663     function(consumer->function()->id())
664         ->RegisterExecutionModelLimitation([errorVUID](SpvExecutionModel model,
665                                                        std::string* message) {
666           if (model != SpvExecutionModelRayGenerationKHR &&
667               model != SpvExecutionModelClosestHitKHR &&
668               model != SpvExecutionModelCallableKHR &&
669               model != SpvExecutionModelMissKHR) {
670             if (message) {
671               *message = errorVUID +
672                          "CallableDataKHR Storage Class is limited to "
673                          "RayGenerationKHR, ClosestHitKHR, CallableKHR, and "
674                          "MissKHR execution model";
675             }
676             return false;
677           }
678           return true;
679         });
680   } else if (storage_class == SpvStorageClassIncomingCallableDataKHR) {
681     std::string errorVUID = VkErrorID(4705);
682     function(consumer->function()->id())
683         ->RegisterExecutionModelLimitation([errorVUID](SpvExecutionModel model,
684                                                        std::string* message) {
685           if (model != SpvExecutionModelCallableKHR) {
686             if (message) {
687               *message = errorVUID +
688                          "IncomingCallableDataKHR Storage Class is limited to "
689                          "CallableKHR execution model";
690             }
691             return false;
692           }
693           return true;
694         });
695   } else if (storage_class == SpvStorageClassRayPayloadKHR) {
696     std::string errorVUID = VkErrorID(4698);
697     function(consumer->function()->id())
698         ->RegisterExecutionModelLimitation([errorVUID](SpvExecutionModel model,
699                                                        std::string* message) {
700           if (model != SpvExecutionModelRayGenerationKHR &&
701               model != SpvExecutionModelClosestHitKHR &&
702               model != SpvExecutionModelMissKHR) {
703             if (message) {
704               *message =
705                   errorVUID +
706                   "RayPayloadKHR Storage Class is limited to RayGenerationKHR, "
707                   "ClosestHitKHR, and MissKHR execution model";
708             }
709             return false;
710           }
711           return true;
712         });
713   } else if (storage_class == SpvStorageClassHitAttributeKHR) {
714     std::string errorVUID = VkErrorID(4701);
715     function(consumer->function()->id())
716         ->RegisterExecutionModelLimitation(
717             [errorVUID](SpvExecutionModel model, std::string* message) {
718               if (model != SpvExecutionModelIntersectionKHR &&
719                   model != SpvExecutionModelAnyHitKHR &&
720                   model != SpvExecutionModelClosestHitKHR) {
721                 if (message) {
722                   *message = errorVUID +
723                              "HitAttributeKHR Storage Class is limited to "
724                              "IntersectionKHR, AnyHitKHR, sand ClosestHitKHR "
725                              "execution model";
726                 }
727                 return false;
728               }
729               return true;
730             });
731   } else if (storage_class == SpvStorageClassIncomingRayPayloadKHR) {
732     std::string errorVUID = VkErrorID(4699);
733     function(consumer->function()->id())
734         ->RegisterExecutionModelLimitation(
735             [errorVUID](SpvExecutionModel model, std::string* message) {
736               if (model != SpvExecutionModelAnyHitKHR &&
737                   model != SpvExecutionModelClosestHitKHR &&
738                   model != SpvExecutionModelMissKHR) {
739                 if (message) {
740                   *message =
741                       errorVUID +
742                       "IncomingRayPayloadKHR Storage Class is limited to "
743                       "AnyHitKHR, ClosestHitKHR, and MissKHR execution model";
744                 }
745                 return false;
746               }
747               return true;
748             });
749   } else if (storage_class == SpvStorageClassShaderRecordBufferKHR) {
750     std::string errorVUID = VkErrorID(7119);
751     function(consumer->function()->id())
752         ->RegisterExecutionModelLimitation(
753             [errorVUID](SpvExecutionModel model, std::string* message) {
754               if (model != SpvExecutionModelRayGenerationKHR &&
755                   model != SpvExecutionModelIntersectionKHR &&
756                   model != SpvExecutionModelAnyHitKHR &&
757                   model != SpvExecutionModelClosestHitKHR &&
758                   model != SpvExecutionModelCallableKHR &&
759                   model != SpvExecutionModelMissKHR) {
760                 if (message) {
761                   *message =
762                       errorVUID +
763                       "ShaderRecordBufferKHR Storage Class is limited to "
764                       "RayGenerationKHR, IntersectionKHR, AnyHitKHR, "
765                       "ClosestHitKHR, CallableKHR, and MissKHR execution model";
766                 }
767                 return false;
768               }
769               return true;
770             });
771   } else if (storage_class == SpvStorageClassTaskPayloadWorkgroupEXT) {
772     function(consumer->function()->id())
773         ->RegisterExecutionModelLimitation(
774             [](SpvExecutionModel model, std::string* message) {
775               if (model != SpvExecutionModelTaskEXT &&
776                   model != SpvExecutionModelMeshEXT) {
777                 if (message) {
778                   *message =
779                       "TaskPayloadWorkgroupEXT Storage Class is limited to "
780                       "TaskEXT and MeshKHR execution model";
781                 }
782                 return false;
783               }
784               return true;
785             });
786   }
787 }
788 
getIdBound() const789 uint32_t ValidationState_t::getIdBound() const { return id_bound_; }
790 
setIdBound(const uint32_t bound)791 void ValidationState_t::setIdBound(const uint32_t bound) { id_bound_ = bound; }
792 
RegisterUniqueTypeDeclaration(const Instruction * inst)793 bool ValidationState_t::RegisterUniqueTypeDeclaration(const Instruction* inst) {
794   std::vector<uint32_t> key;
795   key.push_back(static_cast<uint32_t>(inst->opcode()));
796   for (size_t index = 0; index < inst->operands().size(); ++index) {
797     const spv_parsed_operand_t& operand = inst->operand(index);
798 
799     if (operand.type == SPV_OPERAND_TYPE_RESULT_ID) continue;
800 
801     const int words_begin = operand.offset;
802     const int words_end = words_begin + operand.num_words;
803     assert(words_end <= static_cast<int>(inst->words().size()));
804 
805     key.insert(key.end(), inst->words().begin() + words_begin,
806                inst->words().begin() + words_end);
807   }
808 
809   return unique_type_declarations_.insert(std::move(key)).second;
810 }
811 
GetTypeId(uint32_t id) const812 uint32_t ValidationState_t::GetTypeId(uint32_t id) const {
813   const Instruction* inst = FindDef(id);
814   return inst ? inst->type_id() : 0;
815 }
816 
GetIdOpcode(uint32_t id) const817 SpvOp ValidationState_t::GetIdOpcode(uint32_t id) const {
818   const Instruction* inst = FindDef(id);
819   return inst ? inst->opcode() : SpvOpNop;
820 }
821 
GetComponentType(uint32_t id) const822 uint32_t ValidationState_t::GetComponentType(uint32_t id) const {
823   const Instruction* inst = FindDef(id);
824   assert(inst);
825 
826   switch (inst->opcode()) {
827     case SpvOpTypeFloat:
828     case SpvOpTypeInt:
829     case SpvOpTypeBool:
830       return id;
831 
832     case SpvOpTypeVector:
833       return inst->word(2);
834 
835     case SpvOpTypeMatrix:
836       return GetComponentType(inst->word(2));
837 
838     case SpvOpTypeCooperativeMatrixNV:
839       return inst->word(2);
840 
841     default:
842       break;
843   }
844 
845   if (inst->type_id()) return GetComponentType(inst->type_id());
846 
847   assert(0);
848   return 0;
849 }
850 
GetDimension(uint32_t id) const851 uint32_t ValidationState_t::GetDimension(uint32_t id) const {
852   const Instruction* inst = FindDef(id);
853   assert(inst);
854 
855   switch (inst->opcode()) {
856     case SpvOpTypeFloat:
857     case SpvOpTypeInt:
858     case SpvOpTypeBool:
859       return 1;
860 
861     case SpvOpTypeVector:
862     case SpvOpTypeMatrix:
863       return inst->word(3);
864 
865     case SpvOpTypeCooperativeMatrixNV:
866       // Actual dimension isn't known, return 0
867       return 0;
868 
869     default:
870       break;
871   }
872 
873   if (inst->type_id()) return GetDimension(inst->type_id());
874 
875   assert(0);
876   return 0;
877 }
878 
GetBitWidth(uint32_t id) const879 uint32_t ValidationState_t::GetBitWidth(uint32_t id) const {
880   const uint32_t component_type_id = GetComponentType(id);
881   const Instruction* inst = FindDef(component_type_id);
882   assert(inst);
883 
884   if (inst->opcode() == SpvOpTypeFloat || inst->opcode() == SpvOpTypeInt)
885     return inst->word(2);
886 
887   if (inst->opcode() == SpvOpTypeBool) return 1;
888 
889   assert(0);
890   return 0;
891 }
892 
IsVoidType(uint32_t id) const893 bool ValidationState_t::IsVoidType(uint32_t id) const {
894   const Instruction* inst = FindDef(id);
895   return inst && inst->opcode() == SpvOpTypeVoid;
896 }
897 
IsFloatScalarType(uint32_t id) const898 bool ValidationState_t::IsFloatScalarType(uint32_t id) const {
899   const Instruction* inst = FindDef(id);
900   return inst && inst->opcode() == SpvOpTypeFloat;
901 }
902 
IsFloatVectorType(uint32_t id) const903 bool ValidationState_t::IsFloatVectorType(uint32_t id) const {
904   const Instruction* inst = FindDef(id);
905   if (!inst) {
906     return false;
907   }
908 
909   if (inst->opcode() == SpvOpTypeVector) {
910     return IsFloatScalarType(GetComponentType(id));
911   }
912 
913   return false;
914 }
915 
IsFloatScalarOrVectorType(uint32_t id) const916 bool ValidationState_t::IsFloatScalarOrVectorType(uint32_t id) const {
917   const Instruction* inst = FindDef(id);
918   if (!inst) {
919     return false;
920   }
921 
922   if (inst->opcode() == SpvOpTypeFloat) {
923     return true;
924   }
925 
926   if (inst->opcode() == SpvOpTypeVector) {
927     return IsFloatScalarType(GetComponentType(id));
928   }
929 
930   return false;
931 }
932 
IsIntScalarType(uint32_t id) const933 bool ValidationState_t::IsIntScalarType(uint32_t id) const {
934   const Instruction* inst = FindDef(id);
935   return inst && inst->opcode() == SpvOpTypeInt;
936 }
937 
IsIntVectorType(uint32_t id) const938 bool ValidationState_t::IsIntVectorType(uint32_t id) const {
939   const Instruction* inst = FindDef(id);
940   if (!inst) {
941     return false;
942   }
943 
944   if (inst->opcode() == SpvOpTypeVector) {
945     return IsIntScalarType(GetComponentType(id));
946   }
947 
948   return false;
949 }
950 
IsIntScalarOrVectorType(uint32_t id) const951 bool ValidationState_t::IsIntScalarOrVectorType(uint32_t id) const {
952   const Instruction* inst = FindDef(id);
953   if (!inst) {
954     return false;
955   }
956 
957   if (inst->opcode() == SpvOpTypeInt) {
958     return true;
959   }
960 
961   if (inst->opcode() == SpvOpTypeVector) {
962     return IsIntScalarType(GetComponentType(id));
963   }
964 
965   return false;
966 }
967 
IsUnsignedIntScalarType(uint32_t id) const968 bool ValidationState_t::IsUnsignedIntScalarType(uint32_t id) const {
969   const Instruction* inst = FindDef(id);
970   return inst && inst->opcode() == SpvOpTypeInt && inst->word(3) == 0;
971 }
972 
IsUnsignedIntVectorType(uint32_t id) const973 bool ValidationState_t::IsUnsignedIntVectorType(uint32_t id) const {
974   const Instruction* inst = FindDef(id);
975   if (!inst) {
976     return false;
977   }
978 
979   if (inst->opcode() == SpvOpTypeVector) {
980     return IsUnsignedIntScalarType(GetComponentType(id));
981   }
982 
983   return false;
984 }
985 
IsSignedIntScalarType(uint32_t id) const986 bool ValidationState_t::IsSignedIntScalarType(uint32_t id) const {
987   const Instruction* inst = FindDef(id);
988   return inst && inst->opcode() == SpvOpTypeInt && inst->word(3) == 1;
989 }
990 
IsSignedIntVectorType(uint32_t id) const991 bool ValidationState_t::IsSignedIntVectorType(uint32_t id) const {
992   const Instruction* inst = FindDef(id);
993   if (!inst) {
994     return false;
995   }
996 
997   if (inst->opcode() == SpvOpTypeVector) {
998     return IsSignedIntScalarType(GetComponentType(id));
999   }
1000 
1001   return false;
1002 }
1003 
IsBoolScalarType(uint32_t id) const1004 bool ValidationState_t::IsBoolScalarType(uint32_t id) const {
1005   const Instruction* inst = FindDef(id);
1006   return inst && inst->opcode() == SpvOpTypeBool;
1007 }
1008 
IsBoolVectorType(uint32_t id) const1009 bool ValidationState_t::IsBoolVectorType(uint32_t id) const {
1010   const Instruction* inst = FindDef(id);
1011   if (!inst) {
1012     return false;
1013   }
1014 
1015   if (inst->opcode() == SpvOpTypeVector) {
1016     return IsBoolScalarType(GetComponentType(id));
1017   }
1018 
1019   return false;
1020 }
1021 
IsBoolScalarOrVectorType(uint32_t id) const1022 bool ValidationState_t::IsBoolScalarOrVectorType(uint32_t id) const {
1023   const Instruction* inst = FindDef(id);
1024   if (!inst) {
1025     return false;
1026   }
1027 
1028   if (inst->opcode() == SpvOpTypeBool) {
1029     return true;
1030   }
1031 
1032   if (inst->opcode() == SpvOpTypeVector) {
1033     return IsBoolScalarType(GetComponentType(id));
1034   }
1035 
1036   return false;
1037 }
1038 
IsFloatMatrixType(uint32_t id) const1039 bool ValidationState_t::IsFloatMatrixType(uint32_t id) const {
1040   const Instruction* inst = FindDef(id);
1041   if (!inst) {
1042     return false;
1043   }
1044 
1045   if (inst->opcode() == SpvOpTypeMatrix) {
1046     return IsFloatScalarType(GetComponentType(id));
1047   }
1048 
1049   return false;
1050 }
1051 
GetMatrixTypeInfo(uint32_t id,uint32_t * num_rows,uint32_t * num_cols,uint32_t * column_type,uint32_t * component_type) const1052 bool ValidationState_t::GetMatrixTypeInfo(uint32_t id, uint32_t* num_rows,
1053                                           uint32_t* num_cols,
1054                                           uint32_t* column_type,
1055                                           uint32_t* component_type) const {
1056   if (!id) return false;
1057 
1058   const Instruction* mat_inst = FindDef(id);
1059   assert(mat_inst);
1060   if (mat_inst->opcode() != SpvOpTypeMatrix) return false;
1061 
1062   const uint32_t vec_type = mat_inst->word(2);
1063   const Instruction* vec_inst = FindDef(vec_type);
1064   assert(vec_inst);
1065 
1066   if (vec_inst->opcode() != SpvOpTypeVector) {
1067     assert(0);
1068     return false;
1069   }
1070 
1071   *num_cols = mat_inst->word(3);
1072   *num_rows = vec_inst->word(3);
1073   *column_type = mat_inst->word(2);
1074   *component_type = vec_inst->word(2);
1075 
1076   return true;
1077 }
1078 
GetStructMemberTypes(uint32_t struct_type_id,std::vector<uint32_t> * member_types) const1079 bool ValidationState_t::GetStructMemberTypes(
1080     uint32_t struct_type_id, std::vector<uint32_t>* member_types) const {
1081   member_types->clear();
1082   if (!struct_type_id) return false;
1083 
1084   const Instruction* inst = FindDef(struct_type_id);
1085   assert(inst);
1086   if (inst->opcode() != SpvOpTypeStruct) return false;
1087 
1088   *member_types =
1089       std::vector<uint32_t>(inst->words().cbegin() + 2, inst->words().cend());
1090 
1091   if (member_types->empty()) return false;
1092 
1093   return true;
1094 }
1095 
IsPointerType(uint32_t id) const1096 bool ValidationState_t::IsPointerType(uint32_t id) const {
1097   const Instruction* inst = FindDef(id);
1098   return inst && inst->opcode() == SpvOpTypePointer;
1099 }
1100 
GetPointerTypeInfo(uint32_t id,uint32_t * data_type,uint32_t * storage_class) const1101 bool ValidationState_t::GetPointerTypeInfo(uint32_t id, uint32_t* data_type,
1102                                            uint32_t* storage_class) const {
1103   if (!id) return false;
1104 
1105   const Instruction* inst = FindDef(id);
1106   assert(inst);
1107   if (inst->opcode() != SpvOpTypePointer) return false;
1108 
1109   *storage_class = inst->word(2);
1110   *data_type = inst->word(3);
1111   return true;
1112 }
1113 
IsAccelerationStructureType(uint32_t id) const1114 bool ValidationState_t::IsAccelerationStructureType(uint32_t id) const {
1115   const Instruction* inst = FindDef(id);
1116   return inst && inst->opcode() == SpvOpTypeAccelerationStructureKHR;
1117 }
1118 
IsCooperativeMatrixType(uint32_t id) const1119 bool ValidationState_t::IsCooperativeMatrixType(uint32_t id) const {
1120   const Instruction* inst = FindDef(id);
1121   return inst && inst->opcode() == SpvOpTypeCooperativeMatrixNV;
1122 }
1123 
IsFloatCooperativeMatrixType(uint32_t id) const1124 bool ValidationState_t::IsFloatCooperativeMatrixType(uint32_t id) const {
1125   if (!IsCooperativeMatrixType(id)) return false;
1126   return IsFloatScalarType(FindDef(id)->word(2));
1127 }
1128 
IsIntCooperativeMatrixType(uint32_t id) const1129 bool ValidationState_t::IsIntCooperativeMatrixType(uint32_t id) const {
1130   if (!IsCooperativeMatrixType(id)) return false;
1131   return IsIntScalarType(FindDef(id)->word(2));
1132 }
1133 
IsUnsignedIntCooperativeMatrixType(uint32_t id) const1134 bool ValidationState_t::IsUnsignedIntCooperativeMatrixType(uint32_t id) const {
1135   if (!IsCooperativeMatrixType(id)) return false;
1136   return IsUnsignedIntScalarType(FindDef(id)->word(2));
1137 }
1138 
1139 // Either a 32 bit 2-component uint vector or a 64 bit uint scalar
IsUnsigned64BitHandle(uint32_t id) const1140 bool ValidationState_t::IsUnsigned64BitHandle(uint32_t id) const {
1141   return ((IsUnsignedIntScalarType(id) && GetBitWidth(id) == 64) ||
1142           (IsUnsignedIntVectorType(id) && GetDimension(id) == 2 &&
1143            GetBitWidth(id) == 32));
1144 }
1145 
CooperativeMatrixShapesMatch(const Instruction * inst,uint32_t m1,uint32_t m2)1146 spv_result_t ValidationState_t::CooperativeMatrixShapesMatch(
1147     const Instruction* inst, uint32_t m1, uint32_t m2) {
1148   const auto m1_type = FindDef(m1);
1149   const auto m2_type = FindDef(m2);
1150 
1151   if (m1_type->opcode() != SpvOpTypeCooperativeMatrixNV ||
1152       m2_type->opcode() != SpvOpTypeCooperativeMatrixNV) {
1153     return diag(SPV_ERROR_INVALID_DATA, inst)
1154            << "Expected cooperative matrix types";
1155   }
1156 
1157   uint32_t m1_scope_id = m1_type->GetOperandAs<uint32_t>(2);
1158   uint32_t m1_rows_id = m1_type->GetOperandAs<uint32_t>(3);
1159   uint32_t m1_cols_id = m1_type->GetOperandAs<uint32_t>(4);
1160 
1161   uint32_t m2_scope_id = m2_type->GetOperandAs<uint32_t>(2);
1162   uint32_t m2_rows_id = m2_type->GetOperandAs<uint32_t>(3);
1163   uint32_t m2_cols_id = m2_type->GetOperandAs<uint32_t>(4);
1164 
1165   bool m1_is_int32 = false, m1_is_const_int32 = false, m2_is_int32 = false,
1166        m2_is_const_int32 = false;
1167   uint32_t m1_value = 0, m2_value = 0;
1168 
1169   std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
1170       EvalInt32IfConst(m1_scope_id);
1171   std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
1172       EvalInt32IfConst(m2_scope_id);
1173 
1174   if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
1175     return diag(SPV_ERROR_INVALID_DATA, inst)
1176            << "Expected scopes of Matrix and Result Type to be "
1177            << "identical";
1178   }
1179 
1180   std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
1181       EvalInt32IfConst(m1_rows_id);
1182   std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
1183       EvalInt32IfConst(m2_rows_id);
1184 
1185   if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
1186     return diag(SPV_ERROR_INVALID_DATA, inst)
1187            << "Expected rows of Matrix type and Result Type to be "
1188            << "identical";
1189   }
1190 
1191   std::tie(m1_is_int32, m1_is_const_int32, m1_value) =
1192       EvalInt32IfConst(m1_cols_id);
1193   std::tie(m2_is_int32, m2_is_const_int32, m2_value) =
1194       EvalInt32IfConst(m2_cols_id);
1195 
1196   if (m1_is_const_int32 && m2_is_const_int32 && m1_value != m2_value) {
1197     return diag(SPV_ERROR_INVALID_DATA, inst)
1198            << "Expected columns of Matrix type and Result Type to be "
1199            << "identical";
1200   }
1201 
1202   return SPV_SUCCESS;
1203 }
1204 
GetOperandTypeId(const Instruction * inst,size_t operand_index) const1205 uint32_t ValidationState_t::GetOperandTypeId(const Instruction* inst,
1206                                              size_t operand_index) const {
1207   return GetTypeId(inst->GetOperandAs<uint32_t>(operand_index));
1208 }
1209 
GetConstantValUint64(uint32_t id,uint64_t * val) const1210 bool ValidationState_t::GetConstantValUint64(uint32_t id, uint64_t* val) const {
1211   const Instruction* inst = FindDef(id);
1212   if (!inst) {
1213     assert(0 && "Instruction not found");
1214     return false;
1215   }
1216 
1217   if (inst->opcode() != SpvOpConstant && inst->opcode() != SpvOpSpecConstant)
1218     return false;
1219 
1220   if (!IsIntScalarType(inst->type_id())) return false;
1221 
1222   if (inst->words().size() == 4) {
1223     *val = inst->word(3);
1224   } else {
1225     assert(inst->words().size() == 5);
1226     *val = inst->word(3);
1227     *val |= uint64_t(inst->word(4)) << 32;
1228   }
1229   return true;
1230 }
1231 
EvalInt32IfConst(uint32_t id) const1232 std::tuple<bool, bool, uint32_t> ValidationState_t::EvalInt32IfConst(
1233     uint32_t id) const {
1234   const Instruction* const inst = FindDef(id);
1235   assert(inst);
1236   const uint32_t type = inst->type_id();
1237 
1238   if (type == 0 || !IsIntScalarType(type) || GetBitWidth(type) != 32) {
1239     return std::make_tuple(false, false, 0);
1240   }
1241 
1242   // Spec constant values cannot be evaluated so don't consider constant for
1243   // the purpose of this method.
1244   if (!spvOpcodeIsConstant(inst->opcode()) ||
1245       spvOpcodeIsSpecConstant(inst->opcode())) {
1246     return std::make_tuple(true, false, 0);
1247   }
1248 
1249   if (inst->opcode() == SpvOpConstantNull) {
1250     return std::make_tuple(true, true, 0);
1251   }
1252 
1253   assert(inst->words().size() == 4);
1254   return std::make_tuple(true, true, inst->word(3));
1255 }
1256 
ComputeFunctionToEntryPointMapping()1257 void ValidationState_t::ComputeFunctionToEntryPointMapping() {
1258   for (const uint32_t entry_point : entry_points()) {
1259     std::stack<uint32_t> call_stack;
1260     std::set<uint32_t> visited;
1261     call_stack.push(entry_point);
1262     while (!call_stack.empty()) {
1263       const uint32_t called_func_id = call_stack.top();
1264       call_stack.pop();
1265       if (!visited.insert(called_func_id).second) continue;
1266 
1267       function_to_entry_points_[called_func_id].push_back(entry_point);
1268 
1269       const Function* called_func = function(called_func_id);
1270       if (called_func) {
1271         // Other checks should error out on this invalid SPIR-V.
1272         for (const uint32_t new_call : called_func->function_call_targets()) {
1273           call_stack.push(new_call);
1274         }
1275       }
1276     }
1277   }
1278 }
1279 
ComputeRecursiveEntryPoints()1280 void ValidationState_t::ComputeRecursiveEntryPoints() {
1281   for (const Function& func : functions()) {
1282     std::stack<uint32_t> call_stack;
1283     std::set<uint32_t> visited;
1284 
1285     for (const uint32_t new_call : func.function_call_targets()) {
1286       call_stack.push(new_call);
1287     }
1288 
1289     while (!call_stack.empty()) {
1290       const uint32_t called_func_id = call_stack.top();
1291       call_stack.pop();
1292 
1293       if (!visited.insert(called_func_id).second) continue;
1294 
1295       if (called_func_id == func.id()) {
1296         for (const uint32_t entry_point :
1297              function_to_entry_points_[called_func_id])
1298           recursive_entry_points_.insert(entry_point);
1299         break;
1300       }
1301 
1302       const Function* called_func = function(called_func_id);
1303       if (called_func) {
1304         // Other checks should error out on this invalid SPIR-V.
1305         for (const uint32_t new_call : called_func->function_call_targets()) {
1306           call_stack.push(new_call);
1307         }
1308       }
1309     }
1310   }
1311 }
1312 
FunctionEntryPoints(uint32_t func) const1313 const std::vector<uint32_t>& ValidationState_t::FunctionEntryPoints(
1314     uint32_t func) const {
1315   auto iter = function_to_entry_points_.find(func);
1316   if (iter == function_to_entry_points_.end()) {
1317     return empty_ids_;
1318   } else {
1319     return iter->second;
1320   }
1321 }
1322 
EntryPointReferences(uint32_t id) const1323 std::set<uint32_t> ValidationState_t::EntryPointReferences(uint32_t id) const {
1324   std::set<uint32_t> referenced_entry_points;
1325   const auto inst = FindDef(id);
1326   if (!inst) return referenced_entry_points;
1327 
1328   std::vector<const Instruction*> stack;
1329   stack.push_back(inst);
1330   while (!stack.empty()) {
1331     const auto current_inst = stack.back();
1332     stack.pop_back();
1333 
1334     if (const auto func = current_inst->function()) {
1335       // Instruction lives in a function, we can stop searching.
1336       const auto function_entry_points = FunctionEntryPoints(func->id());
1337       referenced_entry_points.insert(function_entry_points.begin(),
1338                                      function_entry_points.end());
1339     } else {
1340       // Instruction is in the global scope, keep searching its uses.
1341       for (auto pair : current_inst->uses()) {
1342         const auto next_inst = pair.first;
1343         stack.push_back(next_inst);
1344       }
1345     }
1346   }
1347 
1348   return referenced_entry_points;
1349 }
1350 
Disassemble(const Instruction & inst) const1351 std::string ValidationState_t::Disassemble(const Instruction& inst) const {
1352   const spv_parsed_instruction_t& c_inst(inst.c_inst());
1353   return Disassemble(c_inst.words, c_inst.num_words);
1354 }
1355 
Disassemble(const uint32_t * words,uint16_t num_words) const1356 std::string ValidationState_t::Disassemble(const uint32_t* words,
1357                                            uint16_t num_words) const {
1358   uint32_t disassembly_options = SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
1359                                  SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES;
1360 
1361   return spvInstructionBinaryToText(context()->target_env, words, num_words,
1362                                     words_, num_words_, disassembly_options);
1363 }
1364 
LogicallyMatch(const Instruction * lhs,const Instruction * rhs,bool check_decorations)1365 bool ValidationState_t::LogicallyMatch(const Instruction* lhs,
1366                                        const Instruction* rhs,
1367                                        bool check_decorations) {
1368   if (lhs->opcode() != rhs->opcode()) {
1369     return false;
1370   }
1371 
1372   if (check_decorations) {
1373     const auto& dec_a = id_decorations(lhs->id());
1374     const auto& dec_b = id_decorations(rhs->id());
1375 
1376     for (const auto& dec : dec_b) {
1377       if (std::find(dec_a.begin(), dec_a.end(), dec) == dec_a.end()) {
1378         return false;
1379       }
1380     }
1381   }
1382 
1383   if (lhs->opcode() == SpvOpTypeArray) {
1384     // Size operands must match.
1385     if (lhs->GetOperandAs<uint32_t>(2u) != rhs->GetOperandAs<uint32_t>(2u)) {
1386       return false;
1387     }
1388 
1389     // Elements must match or logically match.
1390     const auto lhs_ele_id = lhs->GetOperandAs<uint32_t>(1u);
1391     const auto rhs_ele_id = rhs->GetOperandAs<uint32_t>(1u);
1392     if (lhs_ele_id == rhs_ele_id) {
1393       return true;
1394     }
1395 
1396     const auto lhs_ele = FindDef(lhs_ele_id);
1397     const auto rhs_ele = FindDef(rhs_ele_id);
1398     if (!lhs_ele || !rhs_ele) {
1399       return false;
1400     }
1401     return LogicallyMatch(lhs_ele, rhs_ele, check_decorations);
1402   } else if (lhs->opcode() == SpvOpTypeStruct) {
1403     // Number of elements must match.
1404     if (lhs->operands().size() != rhs->operands().size()) {
1405       return false;
1406     }
1407 
1408     for (size_t i = 1u; i < lhs->operands().size(); ++i) {
1409       const auto lhs_ele_id = lhs->GetOperandAs<uint32_t>(i);
1410       const auto rhs_ele_id = rhs->GetOperandAs<uint32_t>(i);
1411       // Elements must match or logically match.
1412       if (lhs_ele_id == rhs_ele_id) {
1413         continue;
1414       }
1415 
1416       const auto lhs_ele = FindDef(lhs_ele_id);
1417       const auto rhs_ele = FindDef(rhs_ele_id);
1418       if (!lhs_ele || !rhs_ele) {
1419         return false;
1420       }
1421 
1422       if (!LogicallyMatch(lhs_ele, rhs_ele, check_decorations)) {
1423         return false;
1424       }
1425     }
1426 
1427     // All checks passed.
1428     return true;
1429   }
1430 
1431   // No other opcodes are acceptable at this point. Arrays and structs are
1432   // caught above and if they're elements are not arrays or structs they are
1433   // required to match exactly.
1434   return false;
1435 }
1436 
TracePointer(const Instruction * inst) const1437 const Instruction* ValidationState_t::TracePointer(
1438     const Instruction* inst) const {
1439   auto base_ptr = inst;
1440   while (base_ptr->opcode() == SpvOpAccessChain ||
1441          base_ptr->opcode() == SpvOpInBoundsAccessChain ||
1442          base_ptr->opcode() == SpvOpPtrAccessChain ||
1443          base_ptr->opcode() == SpvOpInBoundsPtrAccessChain ||
1444          base_ptr->opcode() == SpvOpCopyObject) {
1445     base_ptr = FindDef(base_ptr->GetOperandAs<uint32_t>(2u));
1446   }
1447   return base_ptr;
1448 }
1449 
ContainsType(uint32_t id,const std::function<bool (const Instruction *)> & f,bool traverse_all_types) const1450 bool ValidationState_t::ContainsType(
1451     uint32_t id, const std::function<bool(const Instruction*)>& f,
1452     bool traverse_all_types) const {
1453   const auto inst = FindDef(id);
1454   if (!inst) return false;
1455 
1456   if (f(inst)) return true;
1457 
1458   switch (inst->opcode()) {
1459     case SpvOpTypeArray:
1460     case SpvOpTypeRuntimeArray:
1461     case SpvOpTypeVector:
1462     case SpvOpTypeMatrix:
1463     case SpvOpTypeImage:
1464     case SpvOpTypeSampledImage:
1465     case SpvOpTypeCooperativeMatrixNV:
1466       return ContainsType(inst->GetOperandAs<uint32_t>(1u), f,
1467                           traverse_all_types);
1468     case SpvOpTypePointer:
1469       if (IsForwardPointer(id)) return false;
1470       if (traverse_all_types) {
1471         return ContainsType(inst->GetOperandAs<uint32_t>(2u), f,
1472                             traverse_all_types);
1473       }
1474       break;
1475     case SpvOpTypeFunction:
1476     case SpvOpTypeStruct:
1477       if (inst->opcode() == SpvOpTypeFunction && !traverse_all_types) {
1478         return false;
1479       }
1480       for (uint32_t i = 1; i < inst->operands().size(); ++i) {
1481         if (ContainsType(inst->GetOperandAs<uint32_t>(i), f,
1482                          traverse_all_types)) {
1483           return true;
1484         }
1485       }
1486       break;
1487     default:
1488       break;
1489   }
1490 
1491   return false;
1492 }
1493 
ContainsSizedIntOrFloatType(uint32_t id,SpvOp type,uint32_t width) const1494 bool ValidationState_t::ContainsSizedIntOrFloatType(uint32_t id, SpvOp type,
1495                                                     uint32_t width) const {
1496   if (type != SpvOpTypeInt && type != SpvOpTypeFloat) return false;
1497 
1498   const auto f = [type, width](const Instruction* inst) {
1499     if (inst->opcode() == type) {
1500       return inst->GetOperandAs<uint32_t>(1u) == width;
1501     }
1502     return false;
1503   };
1504   return ContainsType(id, f);
1505 }
1506 
ContainsLimitedUseIntOrFloatType(uint32_t id) const1507 bool ValidationState_t::ContainsLimitedUseIntOrFloatType(uint32_t id) const {
1508   if ((!HasCapability(SpvCapabilityInt16) &&
1509        ContainsSizedIntOrFloatType(id, SpvOpTypeInt, 16)) ||
1510       (!HasCapability(SpvCapabilityInt8) &&
1511        ContainsSizedIntOrFloatType(id, SpvOpTypeInt, 8)) ||
1512       (!HasCapability(SpvCapabilityFloat16) &&
1513        ContainsSizedIntOrFloatType(id, SpvOpTypeFloat, 16))) {
1514     return true;
1515   }
1516   return false;
1517 }
1518 
ContainsRuntimeArray(uint32_t id) const1519 bool ValidationState_t::ContainsRuntimeArray(uint32_t id) const {
1520   const auto f = [](const Instruction* inst) {
1521     return inst->opcode() == SpvOpTypeRuntimeArray;
1522   };
1523   return ContainsType(id, f, /* traverse_all_types = */ false);
1524 }
1525 
IsValidStorageClass(SpvStorageClass storage_class) const1526 bool ValidationState_t::IsValidStorageClass(
1527     SpvStorageClass storage_class) const {
1528   if (spvIsVulkanEnv(context()->target_env)) {
1529     switch (storage_class) {
1530       case SpvStorageClassUniformConstant:
1531       case SpvStorageClassUniform:
1532       case SpvStorageClassStorageBuffer:
1533       case SpvStorageClassInput:
1534       case SpvStorageClassOutput:
1535       case SpvStorageClassImage:
1536       case SpvStorageClassWorkgroup:
1537       case SpvStorageClassPrivate:
1538       case SpvStorageClassFunction:
1539       case SpvStorageClassPushConstant:
1540       case SpvStorageClassPhysicalStorageBuffer:
1541       case SpvStorageClassRayPayloadKHR:
1542       case SpvStorageClassIncomingRayPayloadKHR:
1543       case SpvStorageClassHitAttributeKHR:
1544       case SpvStorageClassCallableDataKHR:
1545       case SpvStorageClassIncomingCallableDataKHR:
1546       case SpvStorageClassShaderRecordBufferKHR:
1547       case SpvStorageClassTaskPayloadWorkgroupEXT:
1548         return true;
1549       default:
1550         return false;
1551     }
1552   }
1553 
1554   return true;
1555 }
1556 
1557 #define VUID_WRAP(vuid) "[" #vuid "] "
1558 
1559 // Currently no 2 VUID share the same id, so no need for |reference|
VkErrorID(uint32_t id,const char *) const1560 std::string ValidationState_t::VkErrorID(uint32_t id,
1561                                          const char* /*reference*/) const {
1562   if (!spvIsVulkanEnv(context_->target_env)) {
1563     return "";
1564   }
1565 
1566   // This large switch case is only searched when an error has occurred.
1567   // If an id is changed, the old case must be modified or removed. Each string
1568   // here is interpreted as being "implemented"
1569 
1570   // Clang format adds spaces between hyphens
1571   // clang-format off
1572   switch (id) {
1573     case 4154:
1574       return VUID_WRAP(VUID-BaryCoordKHR-BaryCoordKHR-04154);
1575     case 4155:
1576       return VUID_WRAP(VUID-BaryCoordKHR-BaryCoordKHR-04155);
1577     case 4156:
1578       return VUID_WRAP(VUID-BaryCoordKHR-BaryCoordKHR-04156);
1579     case 4160:
1580       return VUID_WRAP(VUID-BaryCoordNoPerspKHR-BaryCoordNoPerspKHR-04160);
1581     case 4161:
1582       return VUID_WRAP(VUID-BaryCoordNoPerspKHR-BaryCoordNoPerspKHR-04161);
1583     case 4162:
1584       return VUID_WRAP(VUID-BaryCoordNoPerspKHR-BaryCoordNoPerspKHR-04162);
1585     case 4181:
1586       return VUID_WRAP(VUID-BaseInstance-BaseInstance-04181);
1587     case 4182:
1588       return VUID_WRAP(VUID-BaseInstance-BaseInstance-04182);
1589     case 4183:
1590       return VUID_WRAP(VUID-BaseInstance-BaseInstance-04183);
1591     case 4184:
1592       return VUID_WRAP(VUID-BaseVertex-BaseVertex-04184);
1593     case 4185:
1594       return VUID_WRAP(VUID-BaseVertex-BaseVertex-04185);
1595     case 4186:
1596       return VUID_WRAP(VUID-BaseVertex-BaseVertex-04186);
1597     case 4187:
1598       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04187);
1599     case 4188:
1600       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04188);
1601     case 4189:
1602       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04189);
1603     case 4190:
1604       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04190);
1605     case 4191:
1606       return VUID_WRAP(VUID-ClipDistance-ClipDistance-04191);
1607     case 4196:
1608       return VUID_WRAP(VUID-CullDistance-CullDistance-04196);
1609     case 4197:
1610       return VUID_WRAP(VUID-CullDistance-CullDistance-04197);
1611     case 4198:
1612       return VUID_WRAP(VUID-CullDistance-CullDistance-04198);
1613     case 4199:
1614       return VUID_WRAP(VUID-CullDistance-CullDistance-04199);
1615     case 4200:
1616       return VUID_WRAP(VUID-CullDistance-CullDistance-04200);
1617     case 6735:
1618       return VUID_WRAP(VUID-CullMaskKHR-CullMaskKHR-06735); // Execution Model
1619     case 6736:
1620       return VUID_WRAP(VUID-CullMaskKHR-CullMaskKHR-06736); // input storage
1621     case 6737:
1622       return VUID_WRAP(VUID-CullMaskKHR-CullMaskKHR-06737); // 32 int scalar
1623     case 4205:
1624       return VUID_WRAP(VUID-DeviceIndex-DeviceIndex-04205);
1625     case 4206:
1626       return VUID_WRAP(VUID-DeviceIndex-DeviceIndex-04206);
1627     case 4207:
1628       return VUID_WRAP(VUID-DrawIndex-DrawIndex-04207);
1629     case 4208:
1630       return VUID_WRAP(VUID-DrawIndex-DrawIndex-04208);
1631     case 4209:
1632       return VUID_WRAP(VUID-DrawIndex-DrawIndex-04209);
1633     case 4210:
1634       return VUID_WRAP(VUID-FragCoord-FragCoord-04210);
1635     case 4211:
1636       return VUID_WRAP(VUID-FragCoord-FragCoord-04211);
1637     case 4212:
1638       return VUID_WRAP(VUID-FragCoord-FragCoord-04212);
1639     case 4213:
1640       return VUID_WRAP(VUID-FragDepth-FragDepth-04213);
1641     case 4214:
1642       return VUID_WRAP(VUID-FragDepth-FragDepth-04214);
1643     case 4215:
1644       return VUID_WRAP(VUID-FragDepth-FragDepth-04215);
1645     case 4216:
1646       return VUID_WRAP(VUID-FragDepth-FragDepth-04216);
1647     case 4217:
1648       return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04217);
1649     case 4218:
1650       return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04218);
1651     case 4219:
1652       return VUID_WRAP(VUID-FragInvocationCountEXT-FragInvocationCountEXT-04219);
1653     case 4220:
1654       return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04220);
1655     case 4221:
1656       return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04221);
1657     case 4222:
1658       return VUID_WRAP(VUID-FragSizeEXT-FragSizeEXT-04222);
1659     case 4223:
1660       return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04223);
1661     case 4224:
1662       return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04224);
1663     case 4225:
1664       return VUID_WRAP(VUID-FragStencilRefEXT-FragStencilRefEXT-04225);
1665     case 4229:
1666       return VUID_WRAP(VUID-FrontFacing-FrontFacing-04229);
1667     case 4230:
1668       return VUID_WRAP(VUID-FrontFacing-FrontFacing-04230);
1669     case 4231:
1670       return VUID_WRAP(VUID-FrontFacing-FrontFacing-04231);
1671     case 4232:
1672       return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04232);
1673     case 4233:
1674       return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04233);
1675     case 4234:
1676       return VUID_WRAP(VUID-FullyCoveredEXT-FullyCoveredEXT-04234);
1677     case 4236:
1678       return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04236);
1679     case 4237:
1680       return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04237);
1681     case 4238:
1682       return VUID_WRAP(VUID-GlobalInvocationId-GlobalInvocationId-04238);
1683     case 4239:
1684       return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04239);
1685     case 4240:
1686       return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04240);
1687     case 4241:
1688       return VUID_WRAP(VUID-HelperInvocation-HelperInvocation-04241);
1689     case 4242:
1690       return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04242);
1691     case 4243:
1692       return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04243);
1693     case 4244:
1694       return VUID_WRAP(VUID-HitKindKHR-HitKindKHR-04244);
1695     case 4245:
1696       return VUID_WRAP(VUID-HitTNV-HitTNV-04245);
1697     case 4246:
1698       return VUID_WRAP(VUID-HitTNV-HitTNV-04246);
1699     case 4247:
1700       return VUID_WRAP(VUID-HitTNV-HitTNV-04247);
1701     case 4248:
1702       return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04248);
1703     case 4249:
1704       return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04249);
1705     case 4250:
1706       return VUID_WRAP(VUID-IncomingRayFlagsKHR-IncomingRayFlagsKHR-04250);
1707     case 4251:
1708       return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04251);
1709     case 4252:
1710       return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04252);
1711     case 4253:
1712       return VUID_WRAP(VUID-InstanceCustomIndexKHR-InstanceCustomIndexKHR-04253);
1713     case 4254:
1714       return VUID_WRAP(VUID-InstanceId-InstanceId-04254);
1715     case 4255:
1716       return VUID_WRAP(VUID-InstanceId-InstanceId-04255);
1717     case 4256:
1718       return VUID_WRAP(VUID-InstanceId-InstanceId-04256);
1719     case 4257:
1720       return VUID_WRAP(VUID-InvocationId-InvocationId-04257);
1721     case 4258:
1722       return VUID_WRAP(VUID-InvocationId-InvocationId-04258);
1723     case 4259:
1724       return VUID_WRAP(VUID-InvocationId-InvocationId-04259);
1725     case 4263:
1726       return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04263);
1727     case 4264:
1728       return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04264);
1729     case 4265:
1730       return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04265);
1731     case 4266:
1732       return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04266);
1733     case 4267:
1734       return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04267);
1735     case 4268:
1736       return VUID_WRAP(VUID-LaunchIdKHR-LaunchIdKHR-04268);
1737     case 4269:
1738       return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04269);
1739     case 4270:
1740       return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04270);
1741     case 4271:
1742       return VUID_WRAP(VUID-LaunchSizeKHR-LaunchSizeKHR-04271);
1743     case 4272:
1744       return VUID_WRAP(VUID-Layer-Layer-04272);
1745     case 4273:
1746       return VUID_WRAP(VUID-Layer-Layer-04273);
1747     case 4274:
1748       return VUID_WRAP(VUID-Layer-Layer-04274);
1749     case 4275:
1750       return VUID_WRAP(VUID-Layer-Layer-04275);
1751     case 4276:
1752       return VUID_WRAP(VUID-Layer-Layer-04276);
1753     case 4281:
1754       return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04281);
1755     case 4282:
1756       return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04282);
1757     case 4283:
1758       return VUID_WRAP(VUID-LocalInvocationId-LocalInvocationId-04283);
1759     case 4293:
1760       return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04293);
1761     case 4294:
1762       return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04294);
1763     case 4295:
1764       return VUID_WRAP(VUID-NumSubgroups-NumSubgroups-04295);
1765     case 4296:
1766       return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04296);
1767     case 4297:
1768       return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04297);
1769     case 4298:
1770       return VUID_WRAP(VUID-NumWorkgroups-NumWorkgroups-04298);
1771     case 4299:
1772       return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04299);
1773     case 4300:
1774       return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04300);
1775     case 4301:
1776       return VUID_WRAP(VUID-ObjectRayDirectionKHR-ObjectRayDirectionKHR-04301);
1777     case 4302:
1778       return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04302);
1779     case 4303:
1780       return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04303);
1781     case 4304:
1782       return VUID_WRAP(VUID-ObjectRayOriginKHR-ObjectRayOriginKHR-04304);
1783     case 4305:
1784       return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04305);
1785     case 4306:
1786       return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04306);
1787     case 4307:
1788       return VUID_WRAP(VUID-ObjectToWorldKHR-ObjectToWorldKHR-04307);
1789     case 4308:
1790       return VUID_WRAP(VUID-PatchVertices-PatchVertices-04308);
1791     case 4309:
1792       return VUID_WRAP(VUID-PatchVertices-PatchVertices-04309);
1793     case 4310:
1794       return VUID_WRAP(VUID-PatchVertices-PatchVertices-04310);
1795     case 4311:
1796       return VUID_WRAP(VUID-PointCoord-PointCoord-04311);
1797     case 4312:
1798       return VUID_WRAP(VUID-PointCoord-PointCoord-04312);
1799     case 4313:
1800       return VUID_WRAP(VUID-PointCoord-PointCoord-04313);
1801     case 4314:
1802       return VUID_WRAP(VUID-PointSize-PointSize-04314);
1803     case 4315:
1804       return VUID_WRAP(VUID-PointSize-PointSize-04315);
1805     case 4316:
1806       return VUID_WRAP(VUID-PointSize-PointSize-04316);
1807     case 4317:
1808       return VUID_WRAP(VUID-PointSize-PointSize-04317);
1809     case 4318:
1810       return VUID_WRAP(VUID-Position-Position-04318);
1811     case 4319:
1812       return VUID_WRAP(VUID-Position-Position-04319);
1813     case 4320:
1814       return VUID_WRAP(VUID-Position-Position-04320);
1815     case 4321:
1816       return VUID_WRAP(VUID-Position-Position-04321);
1817     case 4330:
1818       return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04330);
1819     case 4334:
1820       return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04334);
1821     case 4337:
1822       return VUID_WRAP(VUID-PrimitiveId-PrimitiveId-04337);
1823     case 4345:
1824       return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04345);
1825     case 4346:
1826       return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04346);
1827     case 4347:
1828       return VUID_WRAP(VUID-RayGeometryIndexKHR-RayGeometryIndexKHR-04347);
1829     case 4348:
1830       return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04348);
1831     case 4349:
1832       return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04349);
1833     case 4350:
1834       return VUID_WRAP(VUID-RayTmaxKHR-RayTmaxKHR-04350);
1835     case 4351:
1836       return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04351);
1837     case 4352:
1838       return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04352);
1839     case 4353:
1840       return VUID_WRAP(VUID-RayTminKHR-RayTminKHR-04353);
1841     case 4354:
1842       return VUID_WRAP(VUID-SampleId-SampleId-04354);
1843     case 4355:
1844       return VUID_WRAP(VUID-SampleId-SampleId-04355);
1845     case 4356:
1846       return VUID_WRAP(VUID-SampleId-SampleId-04356);
1847     case 4357:
1848       return VUID_WRAP(VUID-SampleMask-SampleMask-04357);
1849     case 4358:
1850       return VUID_WRAP(VUID-SampleMask-SampleMask-04358);
1851     case 4359:
1852       return VUID_WRAP(VUID-SampleMask-SampleMask-04359);
1853     case 4360:
1854       return VUID_WRAP(VUID-SamplePosition-SamplePosition-04360);
1855     case 4361:
1856       return VUID_WRAP(VUID-SamplePosition-SamplePosition-04361);
1857     case 4362:
1858       return VUID_WRAP(VUID-SamplePosition-SamplePosition-04362);
1859     case 4367:
1860       return VUID_WRAP(VUID-SubgroupId-SubgroupId-04367);
1861     case 4368:
1862       return VUID_WRAP(VUID-SubgroupId-SubgroupId-04368);
1863     case 4369:
1864       return VUID_WRAP(VUID-SubgroupId-SubgroupId-04369);
1865     case 4370:
1866       return VUID_WRAP(VUID-SubgroupEqMask-SubgroupEqMask-04370);
1867     case 4371:
1868       return VUID_WRAP(VUID-SubgroupEqMask-SubgroupEqMask-04371);
1869     case 4372:
1870       return VUID_WRAP(VUID-SubgroupGeMask-SubgroupGeMask-04372);
1871     case 4373:
1872       return VUID_WRAP(VUID-SubgroupGeMask-SubgroupGeMask-04373);
1873     case 4374:
1874       return VUID_WRAP(VUID-SubgroupGtMask-SubgroupGtMask-04374);
1875     case 4375:
1876       return VUID_WRAP(VUID-SubgroupGtMask-SubgroupGtMask-04375);
1877     case 4376:
1878       return VUID_WRAP(VUID-SubgroupLeMask-SubgroupLeMask-04376);
1879     case 4377:
1880       return VUID_WRAP(VUID-SubgroupLeMask-SubgroupLeMask-04377);
1881     case 4378:
1882       return VUID_WRAP(VUID-SubgroupLtMask-SubgroupLtMask-04378);
1883     case 4379:
1884       return VUID_WRAP(VUID-SubgroupLtMask-SubgroupLtMask-04379);
1885     case 4380:
1886       return VUID_WRAP(VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-04380);
1887     case 4381:
1888       return VUID_WRAP(VUID-SubgroupLocalInvocationId-SubgroupLocalInvocationId-04381);
1889     case 4382:
1890       return VUID_WRAP(VUID-SubgroupSize-SubgroupSize-04382);
1891     case 4383:
1892       return VUID_WRAP(VUID-SubgroupSize-SubgroupSize-04383);
1893     case 4387:
1894       return VUID_WRAP(VUID-TessCoord-TessCoord-04387);
1895     case 4388:
1896       return VUID_WRAP(VUID-TessCoord-TessCoord-04388);
1897     case 4389:
1898       return VUID_WRAP(VUID-TessCoord-TessCoord-04389);
1899     case 4390:
1900       return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04390);
1901     case 4391:
1902       return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04391);
1903     case 4392:
1904       return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04392);
1905     case 4393:
1906       return VUID_WRAP(VUID-TessLevelOuter-TessLevelOuter-04393);
1907     case 4394:
1908       return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04394);
1909     case 4395:
1910       return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04395);
1911     case 4396:
1912       return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04396);
1913     case 4397:
1914       return VUID_WRAP(VUID-TessLevelInner-TessLevelInner-04397);
1915     case 4398:
1916       return VUID_WRAP(VUID-VertexIndex-VertexIndex-04398);
1917     case 4399:
1918       return VUID_WRAP(VUID-VertexIndex-VertexIndex-04399);
1919     case 4400:
1920       return VUID_WRAP(VUID-VertexIndex-VertexIndex-04400);
1921     case 4401:
1922       return VUID_WRAP(VUID-ViewIndex-ViewIndex-04401);
1923     case 4402:
1924       return VUID_WRAP(VUID-ViewIndex-ViewIndex-04402);
1925     case 4403:
1926       return VUID_WRAP(VUID-ViewIndex-ViewIndex-04403);
1927     case 4404:
1928       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04404);
1929     case 4405:
1930       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04405);
1931     case 4406:
1932       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04406);
1933     case 4407:
1934       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04407);
1935     case 4408:
1936       return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04408);
1937     case 4422:
1938       return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04422);
1939     case 4423:
1940       return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04423);
1941     case 4424:
1942       return VUID_WRAP(VUID-WorkgroupId-WorkgroupId-04424);
1943     case 4425:
1944       return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04425);
1945     case 4426:
1946       return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04426);
1947     case 4427:
1948       return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04427);
1949     case 4428:
1950       return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04428);
1951     case 4429:
1952       return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04429);
1953     case 4430:
1954       return VUID_WRAP(VUID-WorldRayDirectionKHR-WorldRayDirectionKHR-04430);
1955     case 4431:
1956       return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04431);
1957     case 4432:
1958       return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04432);
1959     case 4433:
1960       return VUID_WRAP(VUID-WorldRayOriginKHR-WorldRayOriginKHR-04433);
1961     case 4434:
1962       return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04434);
1963     case 4435:
1964       return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04435);
1965     case 4436:
1966       return VUID_WRAP(VUID-WorldToObjectKHR-WorldToObjectKHR-04436);
1967     case 4484:
1968       return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04484);
1969     case 4485:
1970       return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04485);
1971     case 4486:
1972       return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04486);
1973     case 4490:
1974       return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04490);
1975     case 4491:
1976       return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04491);
1977     case 4492:
1978       return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04492);
1979     case 4633:
1980       return VUID_WRAP(VUID-StandaloneSpirv-None-04633);
1981     case 4634:
1982       return VUID_WRAP(VUID-StandaloneSpirv-None-04634);
1983     case 4635:
1984       return VUID_WRAP(VUID-StandaloneSpirv-None-04635);
1985     case 4636:
1986       return VUID_WRAP(VUID-StandaloneSpirv-None-04636);
1987     case 4637:
1988       return VUID_WRAP(VUID-StandaloneSpirv-None-04637);
1989     case 4638:
1990       return VUID_WRAP(VUID-StandaloneSpirv-None-04638);
1991     case 7321:
1992       return VUID_WRAP(VUID-StandaloneSpirv-None-07321);
1993     case 4640:
1994       return VUID_WRAP(VUID-StandaloneSpirv-None-04640);
1995     case 4641:
1996       return VUID_WRAP(VUID-StandaloneSpirv-None-04641);
1997     case 4642:
1998       return VUID_WRAP(VUID-StandaloneSpirv-None-04642);
1999     case 4643:
2000       return VUID_WRAP(VUID-StandaloneSpirv-None-04643);
2001     case 4644:
2002       return VUID_WRAP(VUID-StandaloneSpirv-None-04644);
2003     case 4645:
2004       return VUID_WRAP(VUID-StandaloneSpirv-None-04645);
2005     case 4651:
2006       return VUID_WRAP(VUID-StandaloneSpirv-OpVariable-04651);
2007     case 4652:
2008       return VUID_WRAP(VUID-StandaloneSpirv-OpReadClockKHR-04652);
2009     case 4653:
2010       return VUID_WRAP(VUID-StandaloneSpirv-OriginLowerLeft-04653);
2011     case 4654:
2012       return VUID_WRAP(VUID-StandaloneSpirv-PixelCenterInteger-04654);
2013     case 4655:
2014       return VUID_WRAP(VUID-StandaloneSpirv-UniformConstant-04655);
2015     case 4656:
2016       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-04656);
2017     case 4657:
2018       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-04657);
2019     case 4658:
2020       return VUID_WRAP(VUID-StandaloneSpirv-OpImageTexelPointer-04658);
2021     case 4659:
2022       return VUID_WRAP(VUID-StandaloneSpirv-OpImageQuerySizeLod-04659);
2023     case 4662:
2024       return VUID_WRAP(VUID-StandaloneSpirv-Offset-04662);
2025     case 4663:
2026       return VUID_WRAP(VUID-StandaloneSpirv-Offset-04663);
2027     case 4664:
2028       return VUID_WRAP(VUID-StandaloneSpirv-OpImageGather-04664);
2029     case 4667:
2030       return VUID_WRAP(VUID-StandaloneSpirv-None-04667);
2031     case 4669:
2032       return VUID_WRAP(VUID-StandaloneSpirv-GLSLShared-04669);
2033     case 4670:
2034       return VUID_WRAP(VUID-StandaloneSpirv-Flat-04670);
2035     case 4675:
2036       return VUID_WRAP(VUID-StandaloneSpirv-FPRoundingMode-04675);
2037     case 4677:
2038       return VUID_WRAP(VUID-StandaloneSpirv-Invariant-04677);
2039     case 4680:
2040       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeRuntimeArray-04680);
2041     case 4682:
2042       return VUID_WRAP(VUID-StandaloneSpirv-OpControlBarrier-04682);
2043     case 6426:
2044       return VUID_WRAP(VUID-StandaloneSpirv-LocalSize-06426); // formally 04683
2045     case 4685:
2046       return VUID_WRAP(VUID-StandaloneSpirv-OpGroupNonUniformBallotBitCount-04685);
2047     case 4686:
2048       return VUID_WRAP(VUID-StandaloneSpirv-None-04686);
2049     case 4698:
2050       return VUID_WRAP(VUID-StandaloneSpirv-RayPayloadKHR-04698);
2051     case 4699:
2052       return VUID_WRAP(VUID-StandaloneSpirv-IncomingRayPayloadKHR-04699);
2053     case 4701:
2054       return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04701);
2055     case 4703:
2056       return VUID_WRAP(VUID-StandaloneSpirv-HitAttributeKHR-04703);
2057     case 4704:
2058       return VUID_WRAP(VUID-StandaloneSpirv-CallableDataKHR-04704);
2059     case 4705:
2060       return VUID_WRAP(VUID-StandaloneSpirv-IncomingCallableDataKHR-04705);
2061     case 7119:
2062       return VUID_WRAP(VUID-StandaloneSpirv-ShaderRecordBufferKHR-07119);
2063     case 4708:
2064       return VUID_WRAP(VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708);
2065     case 4710:
2066       return VUID_WRAP(VUID-StandaloneSpirv-PhysicalStorageBuffer64-04710);
2067     case 4711:
2068       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeForwardPointer-04711);
2069     case 4730:
2070       return VUID_WRAP(VUID-StandaloneSpirv-OpAtomicStore-04730);
2071     case 4731:
2072       return VUID_WRAP(VUID-StandaloneSpirv-OpAtomicLoad-04731);
2073     case 4732:
2074       return VUID_WRAP(VUID-StandaloneSpirv-OpMemoryBarrier-04732);
2075     case 4733:
2076       return VUID_WRAP(VUID-StandaloneSpirv-OpMemoryBarrier-04733);
2077     case 4734:
2078       return VUID_WRAP(VUID-StandaloneSpirv-OpVariable-04734);
2079     case 4744:
2080       return VUID_WRAP(VUID-StandaloneSpirv-Flat-04744);
2081     case 4777:
2082       return VUID_WRAP(VUID-StandaloneSpirv-OpImage-04777);
2083     case 4780:
2084       return VUID_WRAP(VUID-StandaloneSpirv-Result-04780);
2085     case 4781:
2086       return VUID_WRAP(VUID-StandaloneSpirv-Base-04781);
2087     case 4915:
2088       return VUID_WRAP(VUID-StandaloneSpirv-Location-04915);
2089     case 4916:
2090       return VUID_WRAP(VUID-StandaloneSpirv-Location-04916);
2091     case 4917:
2092       return VUID_WRAP(VUID-StandaloneSpirv-Location-04917);
2093     case 4918:
2094       return VUID_WRAP(VUID-StandaloneSpirv-Location-04918);
2095     case 4919:
2096       return VUID_WRAP(VUID-StandaloneSpirv-Location-04919);
2097     case 6201:
2098       return VUID_WRAP(VUID-StandaloneSpirv-Flat-06201);
2099     case 6202:
2100       return VUID_WRAP(VUID-StandaloneSpirv-Flat-06202);
2101     case 6214:
2102       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeImage-06214);
2103     case 6491:
2104       return VUID_WRAP(VUID-StandaloneSpirv-DescriptorSet-06491);
2105     case 6671:
2106       return VUID_WRAP(VUID-StandaloneSpirv-OpTypeSampledImage-06671);
2107     case 6672:
2108       return VUID_WRAP(VUID-StandaloneSpirv-Location-06672);
2109     case 6674:
2110       return VUID_WRAP(VUID-StandaloneSpirv-OpEntryPoint-06674);
2111     case 6675:
2112       return VUID_WRAP(VUID-StandaloneSpirv-PushConstant-06675);
2113     case 6676:
2114       return VUID_WRAP(VUID-StandaloneSpirv-Uniform-06676);
2115     case 6677:
2116       return VUID_WRAP(VUID-StandaloneSpirv-UniformConstant-06677);
2117     case 6678:
2118       return VUID_WRAP(VUID-StandaloneSpirv-InputAttachmentIndex-06678);
2119     case 6777:
2120       return VUID_WRAP(VUID-StandaloneSpirv-PerVertexKHR-06777);
2121     case 6778:
2122       return VUID_WRAP(VUID-StandaloneSpirv-Input-06778);
2123     case 6807:
2124       return VUID_WRAP(VUID-StandaloneSpirv-Uniform-06807);
2125     case 6808:
2126       return VUID_WRAP(VUID-StandaloneSpirv-PushConstant-06808);
2127     case 6925:
2128       return VUID_WRAP(VUID-StandaloneSpirv-Uniform-06925);
2129     case 6997:
2130       return VUID_WRAP(VUID-StandaloneSpirv-SubgroupVoteKHR-06997);
2131     case 7102:
2132       return VUID_WRAP(VUID-StandaloneSpirv-MeshEXT-07102);
2133     case 7320:
2134       return VUID_WRAP(VUID-StandaloneSpirv-ExecutionModel-07320);
2135     case 7290:
2136       return VUID_WRAP(VUID-StandaloneSpirv-Input-07290);
2137     default:
2138       return "";  // unknown id
2139   }
2140   // clang-format on
2141 }
2142 
2143 }  // namespace val
2144 }  // namespace spvtools
2145