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 #ifndef SOURCE_VAL_VALIDATION_STATE_H_ 16 #define SOURCE_VAL_VALIDATION_STATE_H_ 17 18 #include <map> 19 #include <set> 20 #include <string> 21 #include <tuple> 22 #include <unordered_map> 23 #include <unordered_set> 24 #include <vector> 25 26 #include "source/assembly_grammar.h" 27 #include "source/diagnostic.h" 28 #include "source/disassemble.h" 29 #include "source/enum_set.h" 30 #include "source/latest_version_spirv_header.h" 31 #include "source/name_mapper.h" 32 #include "source/spirv_definition.h" 33 #include "source/spirv_validator_options.h" 34 #include "source/val/decoration.h" 35 #include "source/val/function.h" 36 #include "source/val/instruction.h" 37 #include "spirv-tools/libspirv.h" 38 39 namespace spvtools { 40 namespace val { 41 42 /// This enum represents the sections of a SPIRV module. See section 2.4 43 /// of the SPIRV spec for additional details of the order. The enumerant values 44 /// are in the same order as the vector returned by GetModuleOrder 45 enum ModuleLayoutSection { 46 kLayoutCapabilities, /// < Section 2.4 #1 47 kLayoutExtensions, /// < Section 2.4 #2 48 kLayoutExtInstImport, /// < Section 2.4 #3 49 kLayoutMemoryModel, /// < Section 2.4 #4 50 kLayoutEntryPoint, /// < Section 2.4 #5 51 kLayoutExecutionMode, /// < Section 2.4 #6 52 kLayoutDebug1, /// < Section 2.4 #7 > 1 53 kLayoutDebug2, /// < Section 2.4 #7 > 2 54 kLayoutDebug3, /// < Section 2.4 #7 > 3 55 kLayoutAnnotations, /// < Section 2.4 #8 56 kLayoutTypes, /// < Section 2.4 #9 57 kLayoutFunctionDeclarations, /// < Section 2.4 #10 58 kLayoutFunctionDefinitions /// < Section 2.4 #11 59 }; 60 61 /// This class manages the state of the SPIR-V validation as it is being parsed. 62 class ValidationState_t { 63 public: 64 // Features that can optionally be turned on by a capability or environment. 65 struct Feature { 66 bool declare_int16_type = false; // Allow OpTypeInt with 16 bit width? 67 bool declare_float16_type = false; // Allow OpTypeFloat with 16 bit width? 68 bool free_fp_rounding_mode = false; // Allow the FPRoundingMode decoration 69 // and its vaules to be used without 70 // requiring any capability 71 72 // Allow functionalities enabled by VariablePointers capability. 73 bool variable_pointers = false; 74 // Allow functionalities enabled by VariablePointersStorageBuffer 75 // capability. 76 bool variable_pointers_storage_buffer = false; 77 78 // Permit group oerations Reduce, InclusiveScan, ExclusiveScan 79 bool group_ops_reduce_and_scans = false; 80 81 // Disallows the use of OpUndef 82 bool bans_op_undef = false; 83 84 // Allow OpTypeInt with 8 bit width? 85 bool declare_int8_type = false; 86 87 // Target environment uses relaxed block layout. 88 // This is true for Vulkan 1.1 or later. 89 bool env_relaxed_block_layout = false; 90 91 // Allow an OpTypeInt with 8 bit width to be used in more than just int 92 // conversion opcodes 93 bool use_int8_type = false; 94 95 // Use scalar block layout. See VK_EXT_scalar_block_layout: 96 // Defines scalar alignment: 97 // - scalar alignment equals the scalar size in bytes 98 // - array alignment is same as its element alignment 99 // - array alignment is max alignment of any of its members 100 // - vector alignment is same as component alignment 101 // - matrix alignment is same as component alignment 102 // For struct in Uniform, StorageBuffer, PushConstant: 103 // - Offset of a member is multiple of scalar alignment of that member 104 // - ArrayStride and MatrixStride are multiples of scalar alignment 105 // Members need not be listed in offset order 106 bool scalar_block_layout = false; 107 }; 108 109 ValidationState_t(const spv_const_context context, 110 const spv_const_validator_options opt, 111 const uint32_t* words, const size_t num_words, 112 const uint32_t max_warnings); 113 114 /// Returns the context context()115 spv_const_context context() const { return context_; } 116 117 /// Returns the command line options options()118 spv_const_validator_options options() const { return options_; } 119 120 /// Sets the ID of the generator for this module. setGenerator(uint32_t gen)121 void setGenerator(uint32_t gen) { generator_ = gen; } 122 123 /// Returns the ID of the generator for this module. generator()124 uint32_t generator() const { return generator_; } 125 126 /// Sets the SPIR-V version of this module. setVersion(uint32_t ver)127 void setVersion(uint32_t ver) { version_ = ver; } 128 129 /// Gets the SPIR-V version of this module. version()130 uint32_t version() const { return version_; } 131 132 /// Forward declares the id in the module 133 spv_result_t ForwardDeclareId(uint32_t id); 134 135 /// Removes a forward declared ID if it has been defined 136 spv_result_t RemoveIfForwardDeclared(uint32_t id); 137 138 /// Registers an ID as a forward pointer 139 spv_result_t RegisterForwardPointer(uint32_t id); 140 141 /// Returns whether or not an ID is a forward pointer 142 bool IsForwardPointer(uint32_t id) const; 143 144 /// Assigns a name to an ID 145 void AssignNameToId(uint32_t id, std::string name); 146 147 /// Returns a string representation of the ID in the format <id>[Name] where 148 /// the <id> is the numeric valid of the id and the Name is a name assigned by 149 /// the OpName instruction 150 std::string getIdName(uint32_t id) const; 151 152 /// Accessor function for ID bound. 153 uint32_t getIdBound() const; 154 155 /// Mutator function for ID bound. 156 void setIdBound(uint32_t bound); 157 158 /// Returns the number of ID which have been forward referenced but not 159 /// defined 160 size_t unresolved_forward_id_count() const; 161 162 /// Returns a vector of unresolved forward ids. 163 std::vector<uint32_t> UnresolvedForwardIds() const; 164 165 /// Returns true if the id has been defined 166 bool IsDefinedId(uint32_t id) const; 167 168 /// Increments the total number of instructions in the file. increment_total_instructions()169 void increment_total_instructions() { total_instructions_++; } 170 171 /// Increments the total number of functions in the file. increment_total_functions()172 void increment_total_functions() { total_functions_++; } 173 174 /// Allocates internal storage. Note, calling this will invalidate any 175 /// pointers to |ordered_instructions_| or |module_functions_| and, hence, 176 /// should only be called at the beginning of validation. 177 void preallocateStorage(); 178 179 /// Returns the current layout section which is being processed 180 ModuleLayoutSection current_layout_section() const; 181 182 /// Increments the module_layout_order_section_ 183 void ProgressToNextLayoutSectionOrder(); 184 185 /// Determines if the op instruction is part of the current section 186 bool IsOpcodeInCurrentLayoutSection(SpvOp op); 187 188 DiagnosticStream diag(spv_result_t error_code, const Instruction* inst); 189 190 /// Returns the function states 191 std::vector<Function>& functions(); 192 193 /// Returns the function states 194 Function& current_function(); 195 const Function& current_function() const; 196 197 /// Returns function state with the given id, or nullptr if no such function. 198 const Function* function(uint32_t id) const; 199 Function* function(uint32_t id); 200 201 /// Returns true if the called after a function instruction but before the 202 /// function end instruction 203 bool in_function_body() const; 204 205 /// Returns true if called after a label instruction but before a branch 206 /// instruction 207 bool in_block() const; 208 209 struct EntryPointDescription { 210 std::string name; 211 std::vector<uint32_t> interfaces; 212 }; 213 214 /// Registers |id| as an entry point with |execution_model| and |interfaces|. RegisterEntryPoint(const uint32_t id,SpvExecutionModel execution_model,EntryPointDescription && desc)215 void RegisterEntryPoint(const uint32_t id, SpvExecutionModel execution_model, 216 EntryPointDescription&& desc) { 217 entry_points_.push_back(id); 218 entry_point_to_execution_models_[id].insert(execution_model); 219 entry_point_descriptions_[id].emplace_back(desc); 220 } 221 222 /// Returns a list of entry point function ids entry_points()223 const std::vector<uint32_t>& entry_points() const { return entry_points_; } 224 225 /// Returns the set of entry points that root call graphs that contain 226 /// recursion. recursive_entry_points()227 const std::set<uint32_t>& recursive_entry_points() const { 228 return recursive_entry_points_; 229 } 230 231 /// Registers execution mode for the given entry point. RegisterExecutionModeForEntryPoint(uint32_t entry_point,SpvExecutionMode execution_mode)232 void RegisterExecutionModeForEntryPoint(uint32_t entry_point, 233 SpvExecutionMode execution_mode) { 234 entry_point_to_execution_modes_[entry_point].insert(execution_mode); 235 } 236 237 /// Returns the interface descriptions of a given entry point. entry_point_descriptions(uint32_t entry_point)238 const std::vector<EntryPointDescription>& entry_point_descriptions( 239 uint32_t entry_point) { 240 return entry_point_descriptions_.at(entry_point); 241 } 242 243 /// Returns Execution Models for the given Entry Point. 244 /// Returns nullptr if none found (would trigger assertion). GetExecutionModels(uint32_t entry_point)245 const std::set<SpvExecutionModel>* GetExecutionModels( 246 uint32_t entry_point) const { 247 const auto it = entry_point_to_execution_models_.find(entry_point); 248 if (it == entry_point_to_execution_models_.end()) { 249 assert(0); 250 return nullptr; 251 } 252 return &it->second; 253 } 254 255 /// Returns Execution Modes for the given Entry Point. 256 /// Returns nullptr if none found. GetExecutionModes(uint32_t entry_point)257 const std::set<SpvExecutionMode>* GetExecutionModes( 258 uint32_t entry_point) const { 259 const auto it = entry_point_to_execution_modes_.find(entry_point); 260 if (it == entry_point_to_execution_modes_.end()) { 261 return nullptr; 262 } 263 return &it->second; 264 } 265 266 /// Traverses call tree and computes function_to_entry_points_. 267 /// Note: called after fully parsing the binary. 268 void ComputeFunctionToEntryPointMapping(); 269 270 /// Traverse call tree and computes recursive_entry_points_. 271 /// Note: called after fully parsing the binary and calling 272 /// ComputeFunctionToEntryPointMapping. 273 void ComputeRecursiveEntryPoints(); 274 275 /// Returns all the entry points that can call |func|. 276 const std::vector<uint32_t>& FunctionEntryPoints(uint32_t func) const; 277 278 /// Returns all the entry points that statically use |id|. 279 /// 280 /// Note: requires ComputeFunctionToEntryPointMapping to have been called. 281 std::set<uint32_t> EntryPointReferences(uint32_t id) const; 282 283 /// Inserts an <id> to the set of functions that are target of OpFunctionCall. AddFunctionCallTarget(const uint32_t id)284 void AddFunctionCallTarget(const uint32_t id) { 285 function_call_targets_.insert(id); 286 current_function().AddFunctionCallTarget(id); 287 } 288 289 /// Returns whether or not a function<id> is the target of OpFunctionCall. IsFunctionCallTarget(const uint32_t id)290 bool IsFunctionCallTarget(const uint32_t id) { 291 return (function_call_targets_.find(id) != function_call_targets_.end()); 292 } 293 IsFunctionCallDefined(const uint32_t id)294 bool IsFunctionCallDefined(const uint32_t id) { 295 return (id_to_function_.find(id) != id_to_function_.end()); 296 } 297 /// Registers the capability and its dependent capabilities 298 void RegisterCapability(SpvCapability cap); 299 300 /// Registers the extension. 301 void RegisterExtension(Extension ext); 302 303 /// Registers the function in the module. Subsequent instructions will be 304 /// called against this function 305 spv_result_t RegisterFunction(uint32_t id, uint32_t ret_type_id, 306 SpvFunctionControlMask function_control, 307 uint32_t function_type_id); 308 309 /// Register a function end instruction 310 spv_result_t RegisterFunctionEnd(); 311 312 /// Returns true if the capability is enabled in the module. HasCapability(SpvCapability cap)313 bool HasCapability(SpvCapability cap) const { 314 return module_capabilities_.Contains(cap); 315 } 316 317 /// Returns true if the extension is enabled in the module. HasExtension(Extension ext)318 bool HasExtension(Extension ext) const { 319 return module_extensions_.Contains(ext); 320 } 321 322 /// Returns true if any of the capabilities is enabled, or if |capabilities| 323 /// is an empty set. 324 bool HasAnyOfCapabilities(const CapabilitySet& capabilities) const; 325 326 /// Returns true if any of the extensions is enabled, or if |extensions| 327 /// is an empty set. 328 bool HasAnyOfExtensions(const ExtensionSet& extensions) const; 329 330 /// Sets the addressing model of this module (logical/physical). 331 void set_addressing_model(SpvAddressingModel am); 332 333 /// Returns true if the OpMemoryModel was found. has_memory_model_specified()334 bool has_memory_model_specified() const { 335 return addressing_model_ != SpvAddressingModelMax && 336 memory_model_ != SpvMemoryModelMax; 337 } 338 339 /// Returns the addressing model of this module, or Logical if uninitialized. 340 SpvAddressingModel addressing_model() const; 341 342 /// Sets the memory model of this module. 343 void set_memory_model(SpvMemoryModel mm); 344 345 /// Returns the memory model of this module, or Simple if uninitialized. 346 SpvMemoryModel memory_model() const; 347 grammar()348 const AssemblyGrammar& grammar() const { return grammar_; } 349 350 /// Inserts the instruction into the list of ordered instructions in the file. 351 Instruction* AddOrderedInstruction(const spv_parsed_instruction_t* inst); 352 353 /// Registers the instruction. This will add the instruction to the list of 354 /// definitions and register sampled image consumers. 355 void RegisterInstruction(Instruction* inst); 356 357 /// Registers the debug instruction information. 358 void RegisterDebugInstruction(const Instruction* inst); 359 360 /// Registers the decoration for the given <id> RegisterDecorationForId(uint32_t id,const Decoration & dec)361 void RegisterDecorationForId(uint32_t id, const Decoration& dec) { 362 id_decorations_[id].push_back(dec); 363 } 364 365 /// Registers the list of decorations for the given <id> 366 template <class InputIt> RegisterDecorationsForId(uint32_t id,InputIt begin,InputIt end)367 void RegisterDecorationsForId(uint32_t id, InputIt begin, InputIt end) { 368 std::vector<Decoration>& cur_decs = id_decorations_[id]; 369 cur_decs.insert(cur_decs.end(), begin, end); 370 } 371 372 /// Registers the list of decorations for the given member of the given 373 /// structure. 374 template <class InputIt> RegisterDecorationsForStructMember(uint32_t struct_id,uint32_t member_index,InputIt begin,InputIt end)375 void RegisterDecorationsForStructMember(uint32_t struct_id, 376 uint32_t member_index, InputIt begin, 377 InputIt end) { 378 RegisterDecorationsForId(struct_id, begin, end); 379 for (auto& decoration : id_decorations_[struct_id]) { 380 decoration.set_struct_member_index(member_index); 381 } 382 } 383 384 /// Returns all the decorations for the given <id>. If no decorations exist 385 /// for the <id>, it registers an empty vector for it in the map and 386 /// returns the empty vector. id_decorations(uint32_t id)387 std::vector<Decoration>& id_decorations(uint32_t id) { 388 return id_decorations_[id]; 389 } id_decorations(uint32_t id)390 const std::vector<Decoration>& id_decorations(uint32_t id) const { 391 // TODO: This would throw or generate SIGABRT if id has no 392 // decorations. Remove/refactor this function. 393 return id_decorations_.at(id); 394 } 395 396 // Returns const pointer to the internal decoration container. id_decorations()397 const std::map<uint32_t, std::vector<Decoration>>& id_decorations() const { 398 return id_decorations_; 399 } 400 401 /// Finds id's def, if it exists. If found, returns the definition otherwise 402 /// nullptr 403 const Instruction* FindDef(uint32_t id) const; 404 405 /// Finds id's def, if it exists. If found, returns the definition otherwise 406 /// nullptr 407 Instruction* FindDef(uint32_t id); 408 409 /// Returns the instructions in the order they appear in the binary ordered_instructions()410 const std::vector<Instruction>& ordered_instructions() const { 411 return ordered_instructions_; 412 } 413 414 /// Returns a map of instructions mapped by their result id all_definitions()415 const std::unordered_map<uint32_t, Instruction*>& all_definitions() const { 416 return all_definitions_; 417 } 418 419 /// Returns a vector containing the Ids of instructions that consume the given 420 /// SampledImage id. 421 std::vector<uint32_t> getSampledImageConsumers(uint32_t id) const; 422 423 /// Records cons_id as a consumer of sampled_image_id. 424 void RegisterSampledImageConsumer(uint32_t sampled_image_id, 425 uint32_t cons_id); 426 427 /// Returns the set of Global Variables. global_vars()428 std::unordered_set<uint32_t>& global_vars() { return global_vars_; } 429 430 /// Returns the set of Local Variables. local_vars()431 std::unordered_set<uint32_t>& local_vars() { return local_vars_; } 432 433 /// Returns the number of Global Variables. num_global_vars()434 size_t num_global_vars() { return global_vars_.size(); } 435 436 /// Returns the number of Local Variables. num_local_vars()437 size_t num_local_vars() { return local_vars_.size(); } 438 439 /// Inserts a new <id> to the set of Global Variables. registerGlobalVariable(const uint32_t id)440 void registerGlobalVariable(const uint32_t id) { global_vars_.insert(id); } 441 442 /// Inserts a new <id> to the set of Local Variables. registerLocalVariable(const uint32_t id)443 void registerLocalVariable(const uint32_t id) { local_vars_.insert(id); } 444 445 // Returns true if using relaxed block layout, equivalent to 446 // VK_KHR_relaxed_block_layout. IsRelaxedBlockLayout()447 bool IsRelaxedBlockLayout() const { 448 return features_.env_relaxed_block_layout || options()->relax_block_layout; 449 } 450 451 /// Sets the struct nesting depth for a given struct ID set_struct_nesting_depth(uint32_t id,uint32_t depth)452 void set_struct_nesting_depth(uint32_t id, uint32_t depth) { 453 struct_nesting_depth_[id] = depth; 454 } 455 456 /// Returns the nesting depth of a given structure ID struct_nesting_depth(uint32_t id)457 uint32_t struct_nesting_depth(uint32_t id) { 458 return struct_nesting_depth_[id]; 459 } 460 461 /// Records that the structure type has a member decorated with a built-in. RegisterStructTypeWithBuiltInMember(uint32_t id)462 void RegisterStructTypeWithBuiltInMember(uint32_t id) { 463 builtin_structs_.insert(id); 464 } 465 466 /// Returns true if the struct type with the given Id has a BuiltIn member. IsStructTypeWithBuiltInMember(uint32_t id)467 bool IsStructTypeWithBuiltInMember(uint32_t id) const { 468 return (builtin_structs_.find(id) != builtin_structs_.end()); 469 } 470 471 // Returns the state of optional features. features()472 const Feature& features() const { return features_; } 473 474 /// Adds the instruction data to unique_type_declarations_. 475 /// Returns false if an identical type declaration already exists. 476 bool RegisterUniqueTypeDeclaration(const Instruction* inst); 477 478 // Returns type_id of the scalar component of |id|. 479 // |id| can be either 480 // - scalar, vector or matrix type 481 // - object of either scalar, vector or matrix type 482 uint32_t GetComponentType(uint32_t id) const; 483 484 // Returns 485 // - 1 for scalar types or objects 486 // - vector size for vector types or objects 487 // - num columns for matrix types or objects 488 // Should not be called with any other arguments (will return zero and invoke 489 // assertion). 490 uint32_t GetDimension(uint32_t id) const; 491 492 // Returns bit width of scalar or component. 493 // |id| can be 494 // - scalar, vector or matrix type 495 // - object of either scalar, vector or matrix type 496 // Will invoke assertion and return 0 if |id| is none of the above. 497 uint32_t GetBitWidth(uint32_t id) const; 498 499 // Provides detailed information on matrix type. 500 // Returns false iff |id| is not matrix type. 501 bool GetMatrixTypeInfo(uint32_t id, uint32_t* num_rows, uint32_t* num_cols, 502 uint32_t* column_type, uint32_t* component_type) const; 503 504 // Collects struct member types into |member_types|. 505 // Returns false iff not struct type or has no members. 506 // Deletes prior contents of |member_types|. 507 bool GetStructMemberTypes(uint32_t struct_type_id, 508 std::vector<uint32_t>* member_types) const; 509 510 // Returns true iff |id| is a type corresponding to the name of the function. 511 // Only works for types not for objects. 512 bool IsFloatScalarType(uint32_t id) const; 513 bool IsFloatVectorType(uint32_t id) const; 514 bool IsFloatScalarOrVectorType(uint32_t id) const; 515 bool IsFloatMatrixType(uint32_t id) const; 516 bool IsIntScalarType(uint32_t id) const; 517 bool IsIntVectorType(uint32_t id) const; 518 bool IsIntScalarOrVectorType(uint32_t id) const; 519 bool IsUnsignedIntScalarType(uint32_t id) const; 520 bool IsUnsignedIntVectorType(uint32_t id) const; 521 bool IsSignedIntScalarType(uint32_t id) const; 522 bool IsSignedIntVectorType(uint32_t id) const; 523 bool IsBoolScalarType(uint32_t id) const; 524 bool IsBoolVectorType(uint32_t id) const; 525 bool IsBoolScalarOrVectorType(uint32_t id) const; 526 bool IsPointerType(uint32_t id) const; 527 528 // Gets value from OpConstant and OpSpecConstant as uint64. 529 // Returns false on failure (no instruction, wrong instruction, not int). 530 bool GetConstantValUint64(uint32_t id, uint64_t* val) const; 531 532 // Returns type_id if id has type or zero otherwise. 533 uint32_t GetTypeId(uint32_t id) const; 534 535 // Returns opcode of the instruction which issued the id or OpNop if the 536 // instruction is not registered. 537 SpvOp GetIdOpcode(uint32_t id) const; 538 539 // Returns type_id for given id operand if it has a type or zero otherwise. 540 // |operand_index| is expected to be pointing towards an operand which is an 541 // id. 542 uint32_t GetOperandTypeId(const Instruction* inst, 543 size_t operand_index) const; 544 545 // Provides information on pointer type. Returns false iff not pointer type. 546 bool GetPointerTypeInfo(uint32_t id, uint32_t* data_type, 547 uint32_t* storage_class) const; 548 549 // Tries to evaluate a 32-bit signed or unsigned scalar integer constant. 550 // Returns tuple <is_int32, is_const_int32, value>. 551 // OpSpecConstant* return |is_const_int32| as false since their values cannot 552 // be relied upon during validation. 553 std::tuple<bool, bool, uint32_t> EvalInt32IfConst(uint32_t id); 554 555 // Returns the disassembly string for the given instruction. 556 std::string Disassemble(const Instruction& inst) const; 557 558 // Returns the disassembly string for the given instruction. 559 std::string Disassemble(const uint32_t* words, uint16_t num_words) const; 560 561 private: 562 ValidationState_t(const ValidationState_t&); 563 564 const spv_const_context context_; 565 566 /// Stores the Validator command line options. Must be a valid options object. 567 const spv_const_validator_options options_; 568 569 /// The SPIR-V binary module we're validating. 570 const uint32_t* words_; 571 const size_t num_words_; 572 573 /// The generator of the SPIR-V. 574 uint32_t generator_ = 0; 575 576 /// The version of the SPIR-V. 577 uint32_t version_ = 0; 578 579 /// The total number of instructions in the binary. 580 size_t total_instructions_ = 0; 581 /// The total number of functions in the binary. 582 size_t total_functions_ = 0; 583 584 /// IDs which have been forward declared but have not been defined 585 std::unordered_set<uint32_t> unresolved_forward_ids_; 586 587 /// IDs that have been declared as forward pointers. 588 std::unordered_set<uint32_t> forward_pointer_ids_; 589 590 /// Stores a vector of instructions that use the result of a given 591 /// OpSampledImage instruction. 592 std::unordered_map<uint32_t, std::vector<uint32_t>> sampled_image_consumers_; 593 594 /// A map of operand IDs and their names defined by the OpName instruction 595 std::unordered_map<uint32_t, std::string> operand_names_; 596 597 /// The section of the code being processed 598 ModuleLayoutSection current_layout_section_; 599 600 /// A list of functions in the module. 601 /// Pointers to objects in this container are guaranteed to be stable and 602 /// valid until the end of lifetime of the validation state. 603 std::vector<Function> module_functions_; 604 605 /// Capabilities declared in the module 606 CapabilitySet module_capabilities_; 607 608 /// Extensions declared in the module 609 ExtensionSet module_extensions_; 610 611 /// List of all instructions in the order they appear in the binary 612 std::vector<Instruction> ordered_instructions_; 613 614 /// Instructions that can be referenced by Ids 615 std::unordered_map<uint32_t, Instruction*> all_definitions_; 616 617 /// IDs that are entry points, ie, arguments to OpEntryPoint. 618 std::vector<uint32_t> entry_points_; 619 620 /// Maps an entry point id to its desciptions. 621 std::unordered_map<uint32_t, std::vector<EntryPointDescription>> 622 entry_point_descriptions_; 623 624 /// IDs that are entry points, ie, arguments to OpEntryPoint, and root a call 625 /// graph that recurses. 626 std::set<uint32_t> recursive_entry_points_; 627 628 /// Functions IDs that are target of OpFunctionCall. 629 std::unordered_set<uint32_t> function_call_targets_; 630 631 /// ID Bound from the Header 632 uint32_t id_bound_; 633 634 /// Set of Global Variable IDs (Storage Class other than 'Function') 635 std::unordered_set<uint32_t> global_vars_; 636 637 /// Set of Local Variable IDs ('Function' Storage Class) 638 std::unordered_set<uint32_t> local_vars_; 639 640 /// Set of struct types that have members with a BuiltIn decoration. 641 std::unordered_set<uint32_t> builtin_structs_; 642 643 /// Structure Nesting Depth 644 std::unordered_map<uint32_t, uint32_t> struct_nesting_depth_; 645 646 /// Stores the list of decorations for a given <id> 647 std::map<uint32_t, std::vector<Decoration>> id_decorations_; 648 649 /// Stores type declarations which need to be unique (i.e. non-aggregates), 650 /// in the form [opcode, operand words], result_id is not stored. 651 /// Using ordered set to avoid the need for a vector hash function. 652 /// The size of this container is expected not to exceed double-digits. 653 std::set<std::vector<uint32_t>> unique_type_declarations_; 654 655 AssemblyGrammar grammar_; 656 657 SpvAddressingModel addressing_model_; 658 SpvMemoryModel memory_model_; 659 660 /// NOTE: See correspoding getter functions 661 bool in_function_; 662 663 /// The state of optional features. These are determined by capabilities 664 /// declared by the module and the environment. 665 Feature features_; 666 667 /// Maps function ids to function stat objects. 668 std::unordered_map<uint32_t, Function*> id_to_function_; 669 670 /// Mapping entry point -> execution models. It is presumed that the same 671 /// function could theoretically be used as 'main' by multiple OpEntryPoint 672 /// instructions. 673 std::unordered_map<uint32_t, std::set<SpvExecutionModel>> 674 entry_point_to_execution_models_; 675 676 /// Mapping entry point -> execution modes. 677 std::unordered_map<uint32_t, std::set<SpvExecutionMode>> 678 entry_point_to_execution_modes_; 679 680 /// Mapping function -> array of entry points inside this 681 /// module which can (indirectly) call the function. 682 std::unordered_map<uint32_t, std::vector<uint32_t>> function_to_entry_points_; 683 const std::vector<uint32_t> empty_ids_; 684 685 /// Maps ids to friendly names. 686 std::unique_ptr<spvtools::FriendlyNameMapper> friendly_mapper_; 687 spvtools::NameMapper name_mapper_; 688 689 /// Variables used to reduce the number of diagnostic messages. 690 uint32_t num_of_warnings_; 691 uint32_t max_num_of_warnings_; 692 }; 693 694 } // namespace val 695 } // namespace spvtools 696 697 #endif // SOURCE_VAL_VALIDATION_STATE_H_ 698