• 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 #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