1fd4e5da5Sopenharmony_ci// Copyright (c) 2015-2016 The Khronos Group Inc.
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci#ifndef SOURCE_VAL_VALIDATION_STATE_H_
16fd4e5da5Sopenharmony_ci#define SOURCE_VAL_VALIDATION_STATE_H_
17fd4e5da5Sopenharmony_ci
18fd4e5da5Sopenharmony_ci#include <algorithm>
19fd4e5da5Sopenharmony_ci#include <map>
20fd4e5da5Sopenharmony_ci#include <set>
21fd4e5da5Sopenharmony_ci#include <string>
22fd4e5da5Sopenharmony_ci#include <tuple>
23fd4e5da5Sopenharmony_ci#include <unordered_map>
24fd4e5da5Sopenharmony_ci#include <unordered_set>
25fd4e5da5Sopenharmony_ci#include <vector>
26fd4e5da5Sopenharmony_ci
27fd4e5da5Sopenharmony_ci#include "source/assembly_grammar.h"
28fd4e5da5Sopenharmony_ci#include "source/diagnostic.h"
29fd4e5da5Sopenharmony_ci#include "source/disassemble.h"
30fd4e5da5Sopenharmony_ci#include "source/enum_set.h"
31fd4e5da5Sopenharmony_ci#include "source/latest_version_spirv_header.h"
32fd4e5da5Sopenharmony_ci#include "source/name_mapper.h"
33fd4e5da5Sopenharmony_ci#include "source/spirv_definition.h"
34fd4e5da5Sopenharmony_ci#include "source/spirv_validator_options.h"
35fd4e5da5Sopenharmony_ci#include "source/val/decoration.h"
36fd4e5da5Sopenharmony_ci#include "source/val/function.h"
37fd4e5da5Sopenharmony_ci#include "source/val/instruction.h"
38fd4e5da5Sopenharmony_ci#include "spirv-tools/libspirv.h"
39fd4e5da5Sopenharmony_ci
40fd4e5da5Sopenharmony_cinamespace spvtools {
41fd4e5da5Sopenharmony_cinamespace val {
42fd4e5da5Sopenharmony_ci
43fd4e5da5Sopenharmony_ci/// This enum represents the sections of a SPIRV module. See section 2.4
44fd4e5da5Sopenharmony_ci/// of the SPIRV spec for additional details of the order. The enumerant values
45fd4e5da5Sopenharmony_ci/// are in the same order as the vector returned by GetModuleOrder
46fd4e5da5Sopenharmony_cienum ModuleLayoutSection {
47fd4e5da5Sopenharmony_ci  kLayoutCapabilities,             /// < Section 2.4 #1
48fd4e5da5Sopenharmony_ci  kLayoutExtensions,               /// < Section 2.4 #2
49fd4e5da5Sopenharmony_ci  kLayoutExtInstImport,            /// < Section 2.4 #3
50fd4e5da5Sopenharmony_ci  kLayoutMemoryModel,              /// < Section 2.4 #4
51fd4e5da5Sopenharmony_ci  kLayoutSamplerImageAddressMode,  /// < Section 2.4 #5
52fd4e5da5Sopenharmony_ci  kLayoutEntryPoint,               /// < Section 2.4 #6
53fd4e5da5Sopenharmony_ci  kLayoutExecutionMode,            /// < Section 2.4 #7
54fd4e5da5Sopenharmony_ci  kLayoutDebug1,                   /// < Section 2.4 #8 > 1
55fd4e5da5Sopenharmony_ci  kLayoutDebug2,                   /// < Section 2.4 #8 > 2
56fd4e5da5Sopenharmony_ci  kLayoutDebug3,                   /// < Section 2.4 #8 > 3
57fd4e5da5Sopenharmony_ci  kLayoutAnnotations,              /// < Section 2.4 #9
58fd4e5da5Sopenharmony_ci  kLayoutTypes,                    /// < Section 2.4 #10
59fd4e5da5Sopenharmony_ci  kLayoutFunctionDeclarations,     /// < Section 2.4 #11
60fd4e5da5Sopenharmony_ci  kLayoutFunctionDefinitions       /// < Section 2.4 #12
61fd4e5da5Sopenharmony_ci};
62fd4e5da5Sopenharmony_ci
63fd4e5da5Sopenharmony_ci/// This class manages the state of the SPIR-V validation as it is being parsed.
64fd4e5da5Sopenharmony_ciclass ValidationState_t {
65fd4e5da5Sopenharmony_ci public:
66fd4e5da5Sopenharmony_ci  // Features that can optionally be turned on by a capability or environment.
67fd4e5da5Sopenharmony_ci  struct Feature {
68fd4e5da5Sopenharmony_ci    bool declare_int16_type = false;     // Allow OpTypeInt with 16 bit width?
69fd4e5da5Sopenharmony_ci    bool declare_float16_type = false;   // Allow OpTypeFloat with 16 bit width?
70fd4e5da5Sopenharmony_ci    bool free_fp_rounding_mode = false;  // Allow the FPRoundingMode decoration
71fd4e5da5Sopenharmony_ci                                         // and its values to be used without
72fd4e5da5Sopenharmony_ci                                         // requiring any capability
73fd4e5da5Sopenharmony_ci
74fd4e5da5Sopenharmony_ci    // Allow functionalities enabled by VariablePointers or
75fd4e5da5Sopenharmony_ci    // VariablePointersStorageBuffer capability.
76fd4e5da5Sopenharmony_ci    bool variable_pointers = false;
77fd4e5da5Sopenharmony_ci
78fd4e5da5Sopenharmony_ci    // Permit group oerations Reduce, InclusiveScan, ExclusiveScan
79fd4e5da5Sopenharmony_ci    bool group_ops_reduce_and_scans = false;
80fd4e5da5Sopenharmony_ci
81fd4e5da5Sopenharmony_ci    // Allow OpTypeInt with 8 bit width?
82fd4e5da5Sopenharmony_ci    bool declare_int8_type = false;
83fd4e5da5Sopenharmony_ci
84fd4e5da5Sopenharmony_ci    // Target environment uses relaxed block layout.
85fd4e5da5Sopenharmony_ci    // This is true for Vulkan 1.1 or later.
86fd4e5da5Sopenharmony_ci    bool env_relaxed_block_layout = false;
87fd4e5da5Sopenharmony_ci
88fd4e5da5Sopenharmony_ci    // Allow an OpTypeInt with 8 bit width to be used in more than just int
89fd4e5da5Sopenharmony_ci    // conversion opcodes
90fd4e5da5Sopenharmony_ci    bool use_int8_type = false;
91fd4e5da5Sopenharmony_ci
92fd4e5da5Sopenharmony_ci    // SPIR-V 1.4 allows us to select between any two composite values
93fd4e5da5Sopenharmony_ci    // of the same type.
94fd4e5da5Sopenharmony_ci    bool select_between_composites = false;
95fd4e5da5Sopenharmony_ci
96fd4e5da5Sopenharmony_ci    // SPIR-V 1.4 allows two memory access operands for OpCopyMemory and
97fd4e5da5Sopenharmony_ci    // OpCopyMemorySized.
98fd4e5da5Sopenharmony_ci    bool copy_memory_permits_two_memory_accesses = false;
99fd4e5da5Sopenharmony_ci
100fd4e5da5Sopenharmony_ci    // SPIR-V 1.4 allows UConvert as a spec constant op in any environment.
101fd4e5da5Sopenharmony_ci    // The Kernel capability already enables it, separately from this flag.
102fd4e5da5Sopenharmony_ci    bool uconvert_spec_constant_op = false;
103fd4e5da5Sopenharmony_ci
104fd4e5da5Sopenharmony_ci    // SPIR-V 1.4 allows Function and Private variables to be NonWritable
105fd4e5da5Sopenharmony_ci    bool nonwritable_var_in_function_or_private = false;
106fd4e5da5Sopenharmony_ci
107fd4e5da5Sopenharmony_ci    // Whether LocalSizeId execution mode is allowed by the environment.
108fd4e5da5Sopenharmony_ci    bool env_allow_localsizeid = false;
109fd4e5da5Sopenharmony_ci  };
110fd4e5da5Sopenharmony_ci
111fd4e5da5Sopenharmony_ci  ValidationState_t(const spv_const_context context,
112fd4e5da5Sopenharmony_ci                    const spv_const_validator_options opt,
113fd4e5da5Sopenharmony_ci                    const uint32_t* words, const size_t num_words,
114fd4e5da5Sopenharmony_ci                    const uint32_t max_warnings);
115fd4e5da5Sopenharmony_ci
116fd4e5da5Sopenharmony_ci  /// Returns the context
117fd4e5da5Sopenharmony_ci  spv_const_context context() const { return context_; }
118fd4e5da5Sopenharmony_ci
119fd4e5da5Sopenharmony_ci  /// Returns the command line options
120fd4e5da5Sopenharmony_ci  spv_const_validator_options options() const { return options_; }
121fd4e5da5Sopenharmony_ci
122fd4e5da5Sopenharmony_ci  /// Sets the ID of the generator for this module.
123fd4e5da5Sopenharmony_ci  void setGenerator(uint32_t gen) { generator_ = gen; }
124fd4e5da5Sopenharmony_ci
125fd4e5da5Sopenharmony_ci  /// Returns the ID of the generator for this module.
126fd4e5da5Sopenharmony_ci  uint32_t generator() const { return generator_; }
127fd4e5da5Sopenharmony_ci
128fd4e5da5Sopenharmony_ci  /// Sets the SPIR-V version of this module.
129fd4e5da5Sopenharmony_ci  void setVersion(uint32_t ver) { version_ = ver; }
130fd4e5da5Sopenharmony_ci
131fd4e5da5Sopenharmony_ci  /// Gets the SPIR-V version of this module.
132fd4e5da5Sopenharmony_ci  uint32_t version() const { return version_; }
133fd4e5da5Sopenharmony_ci
134fd4e5da5Sopenharmony_ci  /// Forward declares the id in the module
135fd4e5da5Sopenharmony_ci  spv_result_t ForwardDeclareId(uint32_t id);
136fd4e5da5Sopenharmony_ci
137fd4e5da5Sopenharmony_ci  /// Removes a forward declared ID if it has been defined
138fd4e5da5Sopenharmony_ci  spv_result_t RemoveIfForwardDeclared(uint32_t id);
139fd4e5da5Sopenharmony_ci
140fd4e5da5Sopenharmony_ci  /// Registers an ID as a forward pointer
141fd4e5da5Sopenharmony_ci  spv_result_t RegisterForwardPointer(uint32_t id);
142fd4e5da5Sopenharmony_ci
143fd4e5da5Sopenharmony_ci  /// Returns whether or not an ID is a forward pointer
144fd4e5da5Sopenharmony_ci  bool IsForwardPointer(uint32_t id) const;
145fd4e5da5Sopenharmony_ci
146fd4e5da5Sopenharmony_ci  /// Assigns a name to an ID
147fd4e5da5Sopenharmony_ci  void AssignNameToId(uint32_t id, std::string name);
148fd4e5da5Sopenharmony_ci
149fd4e5da5Sopenharmony_ci  /// Returns a string representation of the ID in the format <id>[Name] where
150fd4e5da5Sopenharmony_ci  /// the <id> is the numeric valid of the id and the Name is a name assigned by
151fd4e5da5Sopenharmony_ci  /// the OpName instruction
152fd4e5da5Sopenharmony_ci  std::string getIdName(uint32_t id) const;
153fd4e5da5Sopenharmony_ci
154fd4e5da5Sopenharmony_ci  /// Accessor function for ID bound.
155fd4e5da5Sopenharmony_ci  uint32_t getIdBound() const;
156fd4e5da5Sopenharmony_ci
157fd4e5da5Sopenharmony_ci  /// Mutator function for ID bound.
158fd4e5da5Sopenharmony_ci  void setIdBound(uint32_t bound);
159fd4e5da5Sopenharmony_ci
160fd4e5da5Sopenharmony_ci  /// Returns the number of ID which have been forward referenced but not
161fd4e5da5Sopenharmony_ci  /// defined
162fd4e5da5Sopenharmony_ci  size_t unresolved_forward_id_count() const;
163fd4e5da5Sopenharmony_ci
164fd4e5da5Sopenharmony_ci  /// Returns a vector of unresolved forward ids.
165fd4e5da5Sopenharmony_ci  std::vector<uint32_t> UnresolvedForwardIds() const;
166fd4e5da5Sopenharmony_ci
167fd4e5da5Sopenharmony_ci  /// Returns true if the id has been defined
168fd4e5da5Sopenharmony_ci  bool IsDefinedId(uint32_t id) const;
169fd4e5da5Sopenharmony_ci
170fd4e5da5Sopenharmony_ci  /// Increments the total number of instructions in the file.
171fd4e5da5Sopenharmony_ci  void increment_total_instructions() { total_instructions_++; }
172fd4e5da5Sopenharmony_ci
173fd4e5da5Sopenharmony_ci  /// Increments the total number of functions in the file.
174fd4e5da5Sopenharmony_ci  void increment_total_functions() { total_functions_++; }
175fd4e5da5Sopenharmony_ci
176fd4e5da5Sopenharmony_ci  /// Allocates internal storage. Note, calling this will invalidate any
177fd4e5da5Sopenharmony_ci  /// pointers to |ordered_instructions_| or |module_functions_| and, hence,
178fd4e5da5Sopenharmony_ci  /// should only be called at the beginning of validation.
179fd4e5da5Sopenharmony_ci  void preallocateStorage();
180fd4e5da5Sopenharmony_ci
181fd4e5da5Sopenharmony_ci  /// Returns the current layout section which is being processed
182fd4e5da5Sopenharmony_ci  ModuleLayoutSection current_layout_section() const;
183fd4e5da5Sopenharmony_ci
184fd4e5da5Sopenharmony_ci  /// Increments the module_layout_order_section_
185fd4e5da5Sopenharmony_ci  void ProgressToNextLayoutSectionOrder();
186fd4e5da5Sopenharmony_ci
187fd4e5da5Sopenharmony_ci  /// Determines if the op instruction is in a previous layout section
188fd4e5da5Sopenharmony_ci  bool IsOpcodeInPreviousLayoutSection(spv::Op op);
189fd4e5da5Sopenharmony_ci
190fd4e5da5Sopenharmony_ci  /// Determines if the op instruction is part of the current section
191fd4e5da5Sopenharmony_ci  bool IsOpcodeInCurrentLayoutSection(spv::Op op);
192fd4e5da5Sopenharmony_ci
193fd4e5da5Sopenharmony_ci  DiagnosticStream diag(spv_result_t error_code, const Instruction* inst);
194fd4e5da5Sopenharmony_ci
195fd4e5da5Sopenharmony_ci  /// Returns the function states
196fd4e5da5Sopenharmony_ci  std::vector<Function>& functions();
197fd4e5da5Sopenharmony_ci
198fd4e5da5Sopenharmony_ci  /// Returns the function states
199fd4e5da5Sopenharmony_ci  Function& current_function();
200fd4e5da5Sopenharmony_ci  const Function& current_function() const;
201fd4e5da5Sopenharmony_ci
202fd4e5da5Sopenharmony_ci  /// Returns function state with the given id, or nullptr if no such function.
203fd4e5da5Sopenharmony_ci  const Function* function(uint32_t id) const;
204fd4e5da5Sopenharmony_ci  Function* function(uint32_t id);
205fd4e5da5Sopenharmony_ci
206fd4e5da5Sopenharmony_ci  /// Returns true if the called after a function instruction but before the
207fd4e5da5Sopenharmony_ci  /// function end instruction
208fd4e5da5Sopenharmony_ci  bool in_function_body() const;
209fd4e5da5Sopenharmony_ci
210fd4e5da5Sopenharmony_ci  /// Returns true if called after a label instruction but before a branch
211fd4e5da5Sopenharmony_ci  /// instruction
212fd4e5da5Sopenharmony_ci  bool in_block() const;
213fd4e5da5Sopenharmony_ci
214fd4e5da5Sopenharmony_ci  struct EntryPointDescription {
215fd4e5da5Sopenharmony_ci    std::string name;
216fd4e5da5Sopenharmony_ci    std::vector<uint32_t> interfaces;
217fd4e5da5Sopenharmony_ci  };
218fd4e5da5Sopenharmony_ci
219fd4e5da5Sopenharmony_ci  /// Registers |id| as an entry point with |execution_model| and |interfaces|.
220fd4e5da5Sopenharmony_ci  void RegisterEntryPoint(const uint32_t id,
221fd4e5da5Sopenharmony_ci                          spv::ExecutionModel execution_model,
222fd4e5da5Sopenharmony_ci                          EntryPointDescription&& desc) {
223fd4e5da5Sopenharmony_ci    entry_points_.push_back(id);
224fd4e5da5Sopenharmony_ci    entry_point_to_execution_models_[id].insert(execution_model);
225fd4e5da5Sopenharmony_ci    entry_point_descriptions_[id].emplace_back(desc);
226fd4e5da5Sopenharmony_ci  }
227fd4e5da5Sopenharmony_ci
228fd4e5da5Sopenharmony_ci  /// Returns a list of entry point function ids
229fd4e5da5Sopenharmony_ci  const std::vector<uint32_t>& entry_points() const { return entry_points_; }
230fd4e5da5Sopenharmony_ci
231fd4e5da5Sopenharmony_ci  /// Returns the set of entry points that root call graphs that contain
232fd4e5da5Sopenharmony_ci  /// recursion.
233fd4e5da5Sopenharmony_ci  const std::set<uint32_t>& recursive_entry_points() const {
234fd4e5da5Sopenharmony_ci    return recursive_entry_points_;
235fd4e5da5Sopenharmony_ci  }
236fd4e5da5Sopenharmony_ci
237fd4e5da5Sopenharmony_ci  /// Registers execution mode for the given entry point.
238fd4e5da5Sopenharmony_ci  void RegisterExecutionModeForEntryPoint(uint32_t entry_point,
239fd4e5da5Sopenharmony_ci                                          spv::ExecutionMode execution_mode) {
240fd4e5da5Sopenharmony_ci    entry_point_to_execution_modes_[entry_point].insert(execution_mode);
241fd4e5da5Sopenharmony_ci  }
242fd4e5da5Sopenharmony_ci
243fd4e5da5Sopenharmony_ci  /// Returns the interface descriptions of a given entry point.
244fd4e5da5Sopenharmony_ci  const std::vector<EntryPointDescription>& entry_point_descriptions(
245fd4e5da5Sopenharmony_ci      uint32_t entry_point) {
246fd4e5da5Sopenharmony_ci    return entry_point_descriptions_.at(entry_point);
247fd4e5da5Sopenharmony_ci  }
248fd4e5da5Sopenharmony_ci
249fd4e5da5Sopenharmony_ci  /// Returns Execution Models for the given Entry Point.
250fd4e5da5Sopenharmony_ci  /// Returns nullptr if none found (would trigger assertion).
251fd4e5da5Sopenharmony_ci  const std::set<spv::ExecutionModel>* GetExecutionModels(
252fd4e5da5Sopenharmony_ci      uint32_t entry_point) const {
253fd4e5da5Sopenharmony_ci    const auto it = entry_point_to_execution_models_.find(entry_point);
254fd4e5da5Sopenharmony_ci    if (it == entry_point_to_execution_models_.end()) {
255fd4e5da5Sopenharmony_ci      assert(0);
256fd4e5da5Sopenharmony_ci      return nullptr;
257fd4e5da5Sopenharmony_ci    }
258fd4e5da5Sopenharmony_ci    return &it->second;
259fd4e5da5Sopenharmony_ci  }
260fd4e5da5Sopenharmony_ci
261fd4e5da5Sopenharmony_ci  /// Returns Execution Modes for the given Entry Point.
262fd4e5da5Sopenharmony_ci  /// Returns nullptr if none found.
263fd4e5da5Sopenharmony_ci  const std::set<spv::ExecutionMode>* GetExecutionModes(
264fd4e5da5Sopenharmony_ci      uint32_t entry_point) const {
265fd4e5da5Sopenharmony_ci    const auto it = entry_point_to_execution_modes_.find(entry_point);
266fd4e5da5Sopenharmony_ci    if (it == entry_point_to_execution_modes_.end()) {
267fd4e5da5Sopenharmony_ci      return nullptr;
268fd4e5da5Sopenharmony_ci    }
269fd4e5da5Sopenharmony_ci    return &it->second;
270fd4e5da5Sopenharmony_ci  }
271fd4e5da5Sopenharmony_ci
272fd4e5da5Sopenharmony_ci  /// Traverses call tree and computes function_to_entry_points_.
273fd4e5da5Sopenharmony_ci  /// Note: called after fully parsing the binary.
274fd4e5da5Sopenharmony_ci  void ComputeFunctionToEntryPointMapping();
275fd4e5da5Sopenharmony_ci
276fd4e5da5Sopenharmony_ci  /// Traverse call tree and computes recursive_entry_points_.
277fd4e5da5Sopenharmony_ci  /// Note: called after fully parsing the binary and calling
278fd4e5da5Sopenharmony_ci  /// ComputeFunctionToEntryPointMapping.
279fd4e5da5Sopenharmony_ci  void ComputeRecursiveEntryPoints();
280fd4e5da5Sopenharmony_ci
281fd4e5da5Sopenharmony_ci  /// Returns all the entry points that can call |func|.
282fd4e5da5Sopenharmony_ci  const std::vector<uint32_t>& FunctionEntryPoints(uint32_t func) const;
283fd4e5da5Sopenharmony_ci
284fd4e5da5Sopenharmony_ci  /// Returns all the entry points that statically use |id|.
285fd4e5da5Sopenharmony_ci  ///
286fd4e5da5Sopenharmony_ci  /// Note: requires ComputeFunctionToEntryPointMapping to have been called.
287fd4e5da5Sopenharmony_ci  std::set<uint32_t> EntryPointReferences(uint32_t id) const;
288fd4e5da5Sopenharmony_ci
289fd4e5da5Sopenharmony_ci  /// Inserts an <id> to the set of functions that are target of OpFunctionCall.
290fd4e5da5Sopenharmony_ci  void AddFunctionCallTarget(const uint32_t id) {
291fd4e5da5Sopenharmony_ci    function_call_targets_.insert(id);
292fd4e5da5Sopenharmony_ci    current_function().AddFunctionCallTarget(id);
293fd4e5da5Sopenharmony_ci  }
294fd4e5da5Sopenharmony_ci
295fd4e5da5Sopenharmony_ci  /// Returns whether or not a function<id> is the target of OpFunctionCall.
296fd4e5da5Sopenharmony_ci  bool IsFunctionCallTarget(const uint32_t id) {
297fd4e5da5Sopenharmony_ci    return (function_call_targets_.find(id) != function_call_targets_.end());
298fd4e5da5Sopenharmony_ci  }
299fd4e5da5Sopenharmony_ci
300fd4e5da5Sopenharmony_ci  bool IsFunctionCallDefined(const uint32_t id) {
301fd4e5da5Sopenharmony_ci    return (id_to_function_.find(id) != id_to_function_.end());
302fd4e5da5Sopenharmony_ci  }
303fd4e5da5Sopenharmony_ci  /// Registers the capability and its dependent capabilities
304fd4e5da5Sopenharmony_ci  void RegisterCapability(spv::Capability cap);
305fd4e5da5Sopenharmony_ci
306fd4e5da5Sopenharmony_ci  /// Registers the extension.
307fd4e5da5Sopenharmony_ci  void RegisterExtension(Extension ext);
308fd4e5da5Sopenharmony_ci
309fd4e5da5Sopenharmony_ci  /// Registers the function in the module. Subsequent instructions will be
310fd4e5da5Sopenharmony_ci  /// called against this function
311fd4e5da5Sopenharmony_ci  spv_result_t RegisterFunction(uint32_t id, uint32_t ret_type_id,
312fd4e5da5Sopenharmony_ci                                spv::FunctionControlMask function_control,
313fd4e5da5Sopenharmony_ci                                uint32_t function_type_id);
314fd4e5da5Sopenharmony_ci
315fd4e5da5Sopenharmony_ci  /// Register a function end instruction
316fd4e5da5Sopenharmony_ci  spv_result_t RegisterFunctionEnd();
317fd4e5da5Sopenharmony_ci
318fd4e5da5Sopenharmony_ci  /// Returns true if the capability is enabled in the module.
319fd4e5da5Sopenharmony_ci  bool HasCapability(spv::Capability cap) const {
320fd4e5da5Sopenharmony_ci    return module_capabilities_.contains(cap);
321fd4e5da5Sopenharmony_ci  }
322fd4e5da5Sopenharmony_ci
323fd4e5da5Sopenharmony_ci  /// Returns a reference to the set of capabilities in the module.
324fd4e5da5Sopenharmony_ci  /// This is provided for debuggability.
325fd4e5da5Sopenharmony_ci  const CapabilitySet& module_capabilities() const {
326fd4e5da5Sopenharmony_ci    return module_capabilities_;
327fd4e5da5Sopenharmony_ci  }
328fd4e5da5Sopenharmony_ci
329fd4e5da5Sopenharmony_ci  /// Returns true if the extension is enabled in the module.
330fd4e5da5Sopenharmony_ci  bool HasExtension(Extension ext) const {
331fd4e5da5Sopenharmony_ci    return module_extensions_.contains(ext);
332fd4e5da5Sopenharmony_ci  }
333fd4e5da5Sopenharmony_ci
334fd4e5da5Sopenharmony_ci  /// Returns true if any of the capabilities is enabled, or if |capabilities|
335fd4e5da5Sopenharmony_ci  /// is an empty set.
336fd4e5da5Sopenharmony_ci  bool HasAnyOfCapabilities(const CapabilitySet& capabilities) const;
337fd4e5da5Sopenharmony_ci
338fd4e5da5Sopenharmony_ci  /// Returns true if any of the extensions is enabled, or if |extensions|
339fd4e5da5Sopenharmony_ci  /// is an empty set.
340fd4e5da5Sopenharmony_ci  bool HasAnyOfExtensions(const ExtensionSet& extensions) const;
341fd4e5da5Sopenharmony_ci
342fd4e5da5Sopenharmony_ci  /// Sets the addressing model of this module (logical/physical).
343fd4e5da5Sopenharmony_ci  void set_addressing_model(spv::AddressingModel am);
344fd4e5da5Sopenharmony_ci
345fd4e5da5Sopenharmony_ci  /// Returns true if the OpMemoryModel was found.
346fd4e5da5Sopenharmony_ci  bool has_memory_model_specified() const {
347fd4e5da5Sopenharmony_ci    return addressing_model_ != spv::AddressingModel::Max &&
348fd4e5da5Sopenharmony_ci           memory_model_ != spv::MemoryModel::Max;
349fd4e5da5Sopenharmony_ci  }
350fd4e5da5Sopenharmony_ci
351fd4e5da5Sopenharmony_ci  /// Returns the addressing model of this module, or Logical if uninitialized.
352fd4e5da5Sopenharmony_ci  spv::AddressingModel addressing_model() const;
353fd4e5da5Sopenharmony_ci
354fd4e5da5Sopenharmony_ci  /// Returns the addressing model of this module, or Logical if uninitialized.
355fd4e5da5Sopenharmony_ci  uint32_t pointer_size_and_alignment() const {
356fd4e5da5Sopenharmony_ci    return pointer_size_and_alignment_;
357fd4e5da5Sopenharmony_ci  }
358fd4e5da5Sopenharmony_ci
359fd4e5da5Sopenharmony_ci  /// Sets the memory model of this module.
360fd4e5da5Sopenharmony_ci  void set_memory_model(spv::MemoryModel mm);
361fd4e5da5Sopenharmony_ci
362fd4e5da5Sopenharmony_ci  /// Returns the memory model of this module, or Simple if uninitialized.
363fd4e5da5Sopenharmony_ci  spv::MemoryModel memory_model() const;
364fd4e5da5Sopenharmony_ci
365fd4e5da5Sopenharmony_ci  /// Sets the bit width for sampler/image type variables. If not set, they are
366fd4e5da5Sopenharmony_ci  /// considered opaque
367fd4e5da5Sopenharmony_ci  void set_samplerimage_variable_address_mode(uint32_t bit_width);
368fd4e5da5Sopenharmony_ci
369fd4e5da5Sopenharmony_ci  /// Get the addressing mode currently set. If 0, it means addressing mode is
370fd4e5da5Sopenharmony_ci  /// invalid Sampler/Image type variables must be considered opaque This mode
371fd4e5da5Sopenharmony_ci  /// is only valid after the instruction has been read
372fd4e5da5Sopenharmony_ci  uint32_t samplerimage_variable_address_mode() const;
373fd4e5da5Sopenharmony_ci
374fd4e5da5Sopenharmony_ci  /// Returns true if the OpSamplerImageAddressingModeNV was found.
375fd4e5da5Sopenharmony_ci  bool has_samplerimage_variable_address_mode_specified() const {
376fd4e5da5Sopenharmony_ci    return sampler_image_addressing_mode_ != 0;
377fd4e5da5Sopenharmony_ci  }
378fd4e5da5Sopenharmony_ci
379fd4e5da5Sopenharmony_ci  const AssemblyGrammar& grammar() const { return grammar_; }
380fd4e5da5Sopenharmony_ci
381fd4e5da5Sopenharmony_ci  /// Inserts the instruction into the list of ordered instructions in the file.
382fd4e5da5Sopenharmony_ci  Instruction* AddOrderedInstruction(const spv_parsed_instruction_t* inst);
383fd4e5da5Sopenharmony_ci
384fd4e5da5Sopenharmony_ci  /// Registers the instruction. This will add the instruction to the list of
385fd4e5da5Sopenharmony_ci  /// definitions and register sampled image consumers.
386fd4e5da5Sopenharmony_ci  void RegisterInstruction(Instruction* inst);
387fd4e5da5Sopenharmony_ci
388fd4e5da5Sopenharmony_ci  /// Registers the debug instruction information.
389fd4e5da5Sopenharmony_ci  void RegisterDebugInstruction(const Instruction* inst);
390fd4e5da5Sopenharmony_ci
391fd4e5da5Sopenharmony_ci  /// Registers the decoration for the given <id>
392fd4e5da5Sopenharmony_ci  void RegisterDecorationForId(uint32_t id, const Decoration& dec) {
393fd4e5da5Sopenharmony_ci    auto& dec_list = id_decorations_[id];
394fd4e5da5Sopenharmony_ci    dec_list.insert(dec);
395fd4e5da5Sopenharmony_ci  }
396fd4e5da5Sopenharmony_ci
397fd4e5da5Sopenharmony_ci  /// Registers the list of decorations for the given <id>
398fd4e5da5Sopenharmony_ci  template <class InputIt>
399fd4e5da5Sopenharmony_ci  void RegisterDecorationsForId(uint32_t id, InputIt begin, InputIt end) {
400fd4e5da5Sopenharmony_ci    std::set<Decoration>& cur_decs = id_decorations_[id];
401fd4e5da5Sopenharmony_ci    cur_decs.insert(begin, end);
402fd4e5da5Sopenharmony_ci  }
403fd4e5da5Sopenharmony_ci
404fd4e5da5Sopenharmony_ci  /// Registers the list of decorations for the given member of the given
405fd4e5da5Sopenharmony_ci  /// structure.
406fd4e5da5Sopenharmony_ci  template <class InputIt>
407fd4e5da5Sopenharmony_ci  void RegisterDecorationsForStructMember(uint32_t struct_id,
408fd4e5da5Sopenharmony_ci                                          uint32_t member_index, InputIt begin,
409fd4e5da5Sopenharmony_ci                                          InputIt end) {
410fd4e5da5Sopenharmony_ci    std::set<Decoration>& cur_decs = id_decorations_[struct_id];
411fd4e5da5Sopenharmony_ci    for (InputIt iter = begin; iter != end; ++iter) {
412fd4e5da5Sopenharmony_ci      Decoration dec = *iter;
413fd4e5da5Sopenharmony_ci      dec.set_struct_member_index(member_index);
414fd4e5da5Sopenharmony_ci      cur_decs.insert(dec);
415fd4e5da5Sopenharmony_ci    }
416fd4e5da5Sopenharmony_ci  }
417fd4e5da5Sopenharmony_ci
418fd4e5da5Sopenharmony_ci  /// Returns all the decorations for the given <id>. If no decorations exist
419fd4e5da5Sopenharmony_ci  /// for the <id>, it registers an empty set for it in the map and
420fd4e5da5Sopenharmony_ci  /// returns the empty set.
421fd4e5da5Sopenharmony_ci  std::set<Decoration>& id_decorations(uint32_t id) {
422fd4e5da5Sopenharmony_ci    return id_decorations_[id];
423fd4e5da5Sopenharmony_ci  }
424fd4e5da5Sopenharmony_ci
425fd4e5da5Sopenharmony_ci  /// Returns the range of decorations for the given field of the given <id>.
426fd4e5da5Sopenharmony_ci  struct FieldDecorationsIter {
427fd4e5da5Sopenharmony_ci    std::set<Decoration>::const_iterator begin;
428fd4e5da5Sopenharmony_ci    std::set<Decoration>::const_iterator end;
429fd4e5da5Sopenharmony_ci  };
430fd4e5da5Sopenharmony_ci  FieldDecorationsIter id_member_decorations(uint32_t id,
431fd4e5da5Sopenharmony_ci                                             uint32_t member_index) {
432fd4e5da5Sopenharmony_ci    const auto& decorations = id_decorations_[id];
433fd4e5da5Sopenharmony_ci
434fd4e5da5Sopenharmony_ci    // The decorations are sorted by member_index, so this look up will give the
435fd4e5da5Sopenharmony_ci    // exact range of decorations for this member index.
436fd4e5da5Sopenharmony_ci    Decoration min_decoration((spv::Decoration)0, {}, member_index);
437fd4e5da5Sopenharmony_ci    Decoration max_decoration(spv::Decoration::Max, {}, member_index);
438fd4e5da5Sopenharmony_ci
439fd4e5da5Sopenharmony_ci    FieldDecorationsIter result;
440fd4e5da5Sopenharmony_ci    result.begin = decorations.lower_bound(min_decoration);
441fd4e5da5Sopenharmony_ci    result.end = decorations.upper_bound(max_decoration);
442fd4e5da5Sopenharmony_ci
443fd4e5da5Sopenharmony_ci    return result;
444fd4e5da5Sopenharmony_ci  }
445fd4e5da5Sopenharmony_ci
446fd4e5da5Sopenharmony_ci  // Returns const pointer to the internal decoration container.
447fd4e5da5Sopenharmony_ci  const std::map<uint32_t, std::set<Decoration>>& id_decorations() const {
448fd4e5da5Sopenharmony_ci    return id_decorations_;
449fd4e5da5Sopenharmony_ci  }
450fd4e5da5Sopenharmony_ci
451fd4e5da5Sopenharmony_ci  /// Returns true if the given id <id> has the given decoration <dec>,
452fd4e5da5Sopenharmony_ci  /// otherwise returns false.
453fd4e5da5Sopenharmony_ci  bool HasDecoration(uint32_t id, spv::Decoration dec) {
454fd4e5da5Sopenharmony_ci    const auto& decorations = id_decorations_.find(id);
455fd4e5da5Sopenharmony_ci    if (decorations == id_decorations_.end()) return false;
456fd4e5da5Sopenharmony_ci
457fd4e5da5Sopenharmony_ci    return std::any_of(
458fd4e5da5Sopenharmony_ci        decorations->second.begin(), decorations->second.end(),
459fd4e5da5Sopenharmony_ci        [dec](const Decoration& d) { return dec == d.dec_type(); });
460fd4e5da5Sopenharmony_ci  }
461fd4e5da5Sopenharmony_ci
462fd4e5da5Sopenharmony_ci  /// Finds id's def, if it exists.  If found, returns the definition otherwise
463fd4e5da5Sopenharmony_ci  /// nullptr
464fd4e5da5Sopenharmony_ci  const Instruction* FindDef(uint32_t id) const;
465fd4e5da5Sopenharmony_ci
466fd4e5da5Sopenharmony_ci  /// Finds id's def, if it exists.  If found, returns the definition otherwise
467fd4e5da5Sopenharmony_ci  /// nullptr
468fd4e5da5Sopenharmony_ci  Instruction* FindDef(uint32_t id);
469fd4e5da5Sopenharmony_ci
470fd4e5da5Sopenharmony_ci  /// Returns the instructions in the order they appear in the binary
471fd4e5da5Sopenharmony_ci  const std::vector<Instruction>& ordered_instructions() const {
472fd4e5da5Sopenharmony_ci    return ordered_instructions_;
473fd4e5da5Sopenharmony_ci  }
474fd4e5da5Sopenharmony_ci
475fd4e5da5Sopenharmony_ci  /// Returns a map of instructions mapped by their result id
476fd4e5da5Sopenharmony_ci  const std::unordered_map<uint32_t, Instruction*>& all_definitions() const {
477fd4e5da5Sopenharmony_ci    return all_definitions_;
478fd4e5da5Sopenharmony_ci  }
479fd4e5da5Sopenharmony_ci
480fd4e5da5Sopenharmony_ci  /// Returns a vector containing the instructions that consume the given
481fd4e5da5Sopenharmony_ci  /// SampledImage id.
482fd4e5da5Sopenharmony_ci  std::vector<Instruction*> getSampledImageConsumers(uint32_t id) const;
483fd4e5da5Sopenharmony_ci
484fd4e5da5Sopenharmony_ci  /// Records cons_id as a consumer of sampled_image_id.
485fd4e5da5Sopenharmony_ci  void RegisterSampledImageConsumer(uint32_t sampled_image_id,
486fd4e5da5Sopenharmony_ci                                    Instruction* consumer);
487fd4e5da5Sopenharmony_ci
488fd4e5da5Sopenharmony_ci  // Record a cons_id as a consumer of texture_id
489fd4e5da5Sopenharmony_ci  // if texture 'texture_id' has a QCOM image processing decoration
490fd4e5da5Sopenharmony_ci  // and consumer is a load or a sampled image instruction
491fd4e5da5Sopenharmony_ci  void RegisterQCOMImageProcessingTextureConsumer(uint32_t texture_id,
492fd4e5da5Sopenharmony_ci                                                  const Instruction* consumer0,
493fd4e5da5Sopenharmony_ci                                                  const Instruction* consumer1);
494fd4e5da5Sopenharmony_ci
495fd4e5da5Sopenharmony_ci  // Record a function's storage class consumer instruction
496fd4e5da5Sopenharmony_ci  void RegisterStorageClassConsumer(spv::StorageClass storage_class,
497fd4e5da5Sopenharmony_ci                                    Instruction* consumer);
498fd4e5da5Sopenharmony_ci
499fd4e5da5Sopenharmony_ci  /// Returns the set of Global Variables.
500fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t>& global_vars() { return global_vars_; }
501fd4e5da5Sopenharmony_ci
502fd4e5da5Sopenharmony_ci  /// Returns the set of Local Variables.
503fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t>& local_vars() { return local_vars_; }
504fd4e5da5Sopenharmony_ci
505fd4e5da5Sopenharmony_ci  /// Returns the number of Global Variables.
506fd4e5da5Sopenharmony_ci  size_t num_global_vars() { return global_vars_.size(); }
507fd4e5da5Sopenharmony_ci
508fd4e5da5Sopenharmony_ci  /// Returns the number of Local Variables.
509fd4e5da5Sopenharmony_ci  size_t num_local_vars() { return local_vars_.size(); }
510fd4e5da5Sopenharmony_ci
511fd4e5da5Sopenharmony_ci  /// Inserts a new <id> to the set of Global Variables.
512fd4e5da5Sopenharmony_ci  void registerGlobalVariable(const uint32_t id) { global_vars_.insert(id); }
513fd4e5da5Sopenharmony_ci
514fd4e5da5Sopenharmony_ci  /// Inserts a new <id> to the set of Local Variables.
515fd4e5da5Sopenharmony_ci  void registerLocalVariable(const uint32_t id) { local_vars_.insert(id); }
516fd4e5da5Sopenharmony_ci
517fd4e5da5Sopenharmony_ci  // Returns true if using relaxed block layout, equivalent to
518fd4e5da5Sopenharmony_ci  // VK_KHR_relaxed_block_layout.
519fd4e5da5Sopenharmony_ci  bool IsRelaxedBlockLayout() const {
520fd4e5da5Sopenharmony_ci    return features_.env_relaxed_block_layout || options()->relax_block_layout;
521fd4e5da5Sopenharmony_ci  }
522fd4e5da5Sopenharmony_ci
523fd4e5da5Sopenharmony_ci  // Returns true if allowing localsizeid, either because the environment always
524fd4e5da5Sopenharmony_ci  // allows it, or because it is enabled from the command-line.
525fd4e5da5Sopenharmony_ci  bool IsLocalSizeIdAllowed() const {
526fd4e5da5Sopenharmony_ci    return features_.env_allow_localsizeid || options()->allow_localsizeid;
527fd4e5da5Sopenharmony_ci  }
528fd4e5da5Sopenharmony_ci
529fd4e5da5Sopenharmony_ci  /// Sets the struct nesting depth for a given struct ID
530fd4e5da5Sopenharmony_ci  void set_struct_nesting_depth(uint32_t id, uint32_t depth) {
531fd4e5da5Sopenharmony_ci    struct_nesting_depth_[id] = depth;
532fd4e5da5Sopenharmony_ci  }
533fd4e5da5Sopenharmony_ci
534fd4e5da5Sopenharmony_ci  /// Returns the nesting depth of a given structure ID
535fd4e5da5Sopenharmony_ci  uint32_t struct_nesting_depth(uint32_t id) {
536fd4e5da5Sopenharmony_ci    return struct_nesting_depth_[id];
537fd4e5da5Sopenharmony_ci  }
538fd4e5da5Sopenharmony_ci
539fd4e5da5Sopenharmony_ci  /// Records the has a nested block/bufferblock decorated struct for a given
540fd4e5da5Sopenharmony_ci  /// struct ID
541fd4e5da5Sopenharmony_ci  void SetHasNestedBlockOrBufferBlockStruct(uint32_t id, bool has) {
542fd4e5da5Sopenharmony_ci    struct_has_nested_blockorbufferblock_struct_[id] = has;
543fd4e5da5Sopenharmony_ci  }
544fd4e5da5Sopenharmony_ci
545fd4e5da5Sopenharmony_ci  /// For a given struct ID returns true if it has a nested block/bufferblock
546fd4e5da5Sopenharmony_ci  /// decorated struct
547fd4e5da5Sopenharmony_ci  bool GetHasNestedBlockOrBufferBlockStruct(uint32_t id) {
548fd4e5da5Sopenharmony_ci    return struct_has_nested_blockorbufferblock_struct_[id];
549fd4e5da5Sopenharmony_ci  }
550fd4e5da5Sopenharmony_ci
551fd4e5da5Sopenharmony_ci  /// Records that the structure type has a member decorated with a built-in.
552fd4e5da5Sopenharmony_ci  void RegisterStructTypeWithBuiltInMember(uint32_t id) {
553fd4e5da5Sopenharmony_ci    builtin_structs_.insert(id);
554fd4e5da5Sopenharmony_ci  }
555fd4e5da5Sopenharmony_ci
556fd4e5da5Sopenharmony_ci  /// Returns true if the struct type with the given Id has a BuiltIn member.
557fd4e5da5Sopenharmony_ci  bool IsStructTypeWithBuiltInMember(uint32_t id) const {
558fd4e5da5Sopenharmony_ci    return (builtin_structs_.find(id) != builtin_structs_.end());
559fd4e5da5Sopenharmony_ci  }
560fd4e5da5Sopenharmony_ci
561fd4e5da5Sopenharmony_ci  // Returns the state of optional features.
562fd4e5da5Sopenharmony_ci  const Feature& features() const { return features_; }
563fd4e5da5Sopenharmony_ci
564fd4e5da5Sopenharmony_ci  /// Adds the instruction data to unique_type_declarations_.
565fd4e5da5Sopenharmony_ci  /// Returns false if an identical type declaration already exists.
566fd4e5da5Sopenharmony_ci  bool RegisterUniqueTypeDeclaration(const Instruction* inst);
567fd4e5da5Sopenharmony_ci
568fd4e5da5Sopenharmony_ci  // Returns type_id of the scalar component of |id|.
569fd4e5da5Sopenharmony_ci  // |id| can be either
570fd4e5da5Sopenharmony_ci  // - scalar, vector or matrix type
571fd4e5da5Sopenharmony_ci  // - object of either scalar, vector or matrix type
572fd4e5da5Sopenharmony_ci  uint32_t GetComponentType(uint32_t id) const;
573fd4e5da5Sopenharmony_ci
574fd4e5da5Sopenharmony_ci  // Returns
575fd4e5da5Sopenharmony_ci  // - 1 for scalar types or objects
576fd4e5da5Sopenharmony_ci  // - vector size for vector types or objects
577fd4e5da5Sopenharmony_ci  // - num columns for matrix types or objects
578fd4e5da5Sopenharmony_ci  // Should not be called with any other arguments (will return zero and invoke
579fd4e5da5Sopenharmony_ci  // assertion).
580fd4e5da5Sopenharmony_ci  uint32_t GetDimension(uint32_t id) const;
581fd4e5da5Sopenharmony_ci
582fd4e5da5Sopenharmony_ci  // Returns bit width of scalar or component.
583fd4e5da5Sopenharmony_ci  // |id| can be
584fd4e5da5Sopenharmony_ci  // - scalar, vector or matrix type
585fd4e5da5Sopenharmony_ci  // - object of either scalar, vector or matrix type
586fd4e5da5Sopenharmony_ci  // Will invoke assertion and return 0 if |id| is none of the above.
587fd4e5da5Sopenharmony_ci  uint32_t GetBitWidth(uint32_t id) const;
588fd4e5da5Sopenharmony_ci
589fd4e5da5Sopenharmony_ci  // Provides detailed information on matrix type.
590fd4e5da5Sopenharmony_ci  // Returns false iff |id| is not matrix type.
591fd4e5da5Sopenharmony_ci  bool GetMatrixTypeInfo(uint32_t id, uint32_t* num_rows, uint32_t* num_cols,
592fd4e5da5Sopenharmony_ci                         uint32_t* column_type, uint32_t* component_type) const;
593fd4e5da5Sopenharmony_ci
594fd4e5da5Sopenharmony_ci  // Collects struct member types into |member_types|.
595fd4e5da5Sopenharmony_ci  // Returns false iff not struct type or has no members.
596fd4e5da5Sopenharmony_ci  // Deletes prior contents of |member_types|.
597fd4e5da5Sopenharmony_ci  bool GetStructMemberTypes(uint32_t struct_type_id,
598fd4e5da5Sopenharmony_ci                            std::vector<uint32_t>* member_types) const;
599fd4e5da5Sopenharmony_ci
600fd4e5da5Sopenharmony_ci  // Returns true iff |id| is a type corresponding to the name of the function.
601fd4e5da5Sopenharmony_ci  // Only works for types not for objects.
602fd4e5da5Sopenharmony_ci  bool IsVoidType(uint32_t id) const;
603fd4e5da5Sopenharmony_ci  bool IsFloatScalarType(uint32_t id) const;
604fd4e5da5Sopenharmony_ci  bool IsFloatVectorType(uint32_t id) const;
605fd4e5da5Sopenharmony_ci  bool IsFloatScalarOrVectorType(uint32_t id) const;
606fd4e5da5Sopenharmony_ci  bool IsFloatMatrixType(uint32_t id) const;
607fd4e5da5Sopenharmony_ci  bool IsIntScalarType(uint32_t id) const;
608fd4e5da5Sopenharmony_ci  bool IsIntVectorType(uint32_t id) const;
609fd4e5da5Sopenharmony_ci  bool IsIntScalarOrVectorType(uint32_t id) const;
610fd4e5da5Sopenharmony_ci  bool IsUnsignedIntScalarType(uint32_t id) const;
611fd4e5da5Sopenharmony_ci  bool IsUnsignedIntVectorType(uint32_t id) const;
612fd4e5da5Sopenharmony_ci  bool IsUnsignedIntScalarOrVectorType(uint32_t id) const;
613fd4e5da5Sopenharmony_ci  bool IsSignedIntScalarType(uint32_t id) const;
614fd4e5da5Sopenharmony_ci  bool IsSignedIntVectorType(uint32_t id) const;
615fd4e5da5Sopenharmony_ci  bool IsBoolScalarType(uint32_t id) const;
616fd4e5da5Sopenharmony_ci  bool IsBoolVectorType(uint32_t id) const;
617fd4e5da5Sopenharmony_ci  bool IsBoolScalarOrVectorType(uint32_t id) const;
618fd4e5da5Sopenharmony_ci  bool IsPointerType(uint32_t id) const;
619fd4e5da5Sopenharmony_ci  bool IsAccelerationStructureType(uint32_t id) const;
620fd4e5da5Sopenharmony_ci  bool IsCooperativeMatrixType(uint32_t id) const;
621fd4e5da5Sopenharmony_ci  bool IsCooperativeMatrixNVType(uint32_t id) const;
622fd4e5da5Sopenharmony_ci  bool IsCooperativeMatrixKHRType(uint32_t id) const;
623fd4e5da5Sopenharmony_ci  bool IsCooperativeMatrixAType(uint32_t id) const;
624fd4e5da5Sopenharmony_ci  bool IsCooperativeMatrixBType(uint32_t id) const;
625fd4e5da5Sopenharmony_ci  bool IsCooperativeMatrixAccType(uint32_t id) const;
626fd4e5da5Sopenharmony_ci  bool IsFloatCooperativeMatrixType(uint32_t id) const;
627fd4e5da5Sopenharmony_ci  bool IsIntCooperativeMatrixType(uint32_t id) const;
628fd4e5da5Sopenharmony_ci  bool IsUnsignedIntCooperativeMatrixType(uint32_t id) const;
629fd4e5da5Sopenharmony_ci  bool IsUnsigned64BitHandle(uint32_t id) const;
630fd4e5da5Sopenharmony_ci
631fd4e5da5Sopenharmony_ci  // Returns true if |id| is a type id that contains |type| (or integer or
632fd4e5da5Sopenharmony_ci  // floating point type) of |width| bits.
633fd4e5da5Sopenharmony_ci  bool ContainsSizedIntOrFloatType(uint32_t id, spv::Op type,
634fd4e5da5Sopenharmony_ci                                   uint32_t width) const;
635fd4e5da5Sopenharmony_ci  // Returns true if |id| is a type id that contains a 8- or 16-bit int or
636fd4e5da5Sopenharmony_ci  // 16-bit float that is not generally enabled for use.
637fd4e5da5Sopenharmony_ci  bool ContainsLimitedUseIntOrFloatType(uint32_t id) const;
638fd4e5da5Sopenharmony_ci
639fd4e5da5Sopenharmony_ci  // Returns true if |id| is a type that contains a runtime-sized array.
640fd4e5da5Sopenharmony_ci  // Does not consider a pointers as contains the array.
641fd4e5da5Sopenharmony_ci  bool ContainsRuntimeArray(uint32_t id) const;
642fd4e5da5Sopenharmony_ci
643fd4e5da5Sopenharmony_ci  // Generic type traversal.
644fd4e5da5Sopenharmony_ci  // Only traverse pointers and functions if |traverse_all_types| is true.
645fd4e5da5Sopenharmony_ci  // Recursively tests |f| against the type hierarchy headed by |id|.
646fd4e5da5Sopenharmony_ci  bool ContainsType(uint32_t id,
647fd4e5da5Sopenharmony_ci                    const std::function<bool(const Instruction*)>& f,
648fd4e5da5Sopenharmony_ci                    bool traverse_all_types = true) const;
649fd4e5da5Sopenharmony_ci
650fd4e5da5Sopenharmony_ci  // Gets value from OpConstant and OpSpecConstant as uint64.
651fd4e5da5Sopenharmony_ci  // Returns false on failure (no instruction, wrong instruction, not int).
652fd4e5da5Sopenharmony_ci  bool GetConstantValUint64(uint32_t id, uint64_t* val) const;
653fd4e5da5Sopenharmony_ci
654fd4e5da5Sopenharmony_ci  // Returns type_id if id has type or zero otherwise.
655fd4e5da5Sopenharmony_ci  uint32_t GetTypeId(uint32_t id) const;
656fd4e5da5Sopenharmony_ci
657fd4e5da5Sopenharmony_ci  // Returns opcode of the instruction which issued the id or OpNop if the
658fd4e5da5Sopenharmony_ci  // instruction is not registered.
659fd4e5da5Sopenharmony_ci  spv::Op GetIdOpcode(uint32_t id) const;
660fd4e5da5Sopenharmony_ci
661fd4e5da5Sopenharmony_ci  // Returns type_id for given id operand if it has a type or zero otherwise.
662fd4e5da5Sopenharmony_ci  // |operand_index| is expected to be pointing towards an operand which is an
663fd4e5da5Sopenharmony_ci  // id.
664fd4e5da5Sopenharmony_ci  uint32_t GetOperandTypeId(const Instruction* inst,
665fd4e5da5Sopenharmony_ci                            size_t operand_index) const;
666fd4e5da5Sopenharmony_ci
667fd4e5da5Sopenharmony_ci  // Provides information on pointer type. Returns false iff not pointer type.
668fd4e5da5Sopenharmony_ci  bool GetPointerTypeInfo(uint32_t id, uint32_t* data_type,
669fd4e5da5Sopenharmony_ci                          spv::StorageClass* storage_class) const;
670fd4e5da5Sopenharmony_ci
671fd4e5da5Sopenharmony_ci  // Is the ID the type of a pointer to a uniform block: Block-decorated struct
672fd4e5da5Sopenharmony_ci  // in uniform storage class? The result is only valid after internal method
673fd4e5da5Sopenharmony_ci  // CheckDecorationsOfBuffers has been called.
674fd4e5da5Sopenharmony_ci  bool IsPointerToUniformBlock(uint32_t type_id) const {
675fd4e5da5Sopenharmony_ci    return pointer_to_uniform_block_.find(type_id) !=
676fd4e5da5Sopenharmony_ci           pointer_to_uniform_block_.cend();
677fd4e5da5Sopenharmony_ci  }
678fd4e5da5Sopenharmony_ci  // Save the ID of a pointer to uniform block.
679fd4e5da5Sopenharmony_ci  void RegisterPointerToUniformBlock(uint32_t type_id) {
680fd4e5da5Sopenharmony_ci    pointer_to_uniform_block_.insert(type_id);
681fd4e5da5Sopenharmony_ci  }
682fd4e5da5Sopenharmony_ci  // Is the ID the type of a struct used as a uniform block?
683fd4e5da5Sopenharmony_ci  // The result is only valid after internal method CheckDecorationsOfBuffers
684fd4e5da5Sopenharmony_ci  // has been called.
685fd4e5da5Sopenharmony_ci  bool IsStructForUniformBlock(uint32_t type_id) const {
686fd4e5da5Sopenharmony_ci    return struct_for_uniform_block_.find(type_id) !=
687fd4e5da5Sopenharmony_ci           struct_for_uniform_block_.cend();
688fd4e5da5Sopenharmony_ci  }
689fd4e5da5Sopenharmony_ci  // Save the ID of a struct of a uniform block.
690fd4e5da5Sopenharmony_ci  void RegisterStructForUniformBlock(uint32_t type_id) {
691fd4e5da5Sopenharmony_ci    struct_for_uniform_block_.insert(type_id);
692fd4e5da5Sopenharmony_ci  }
693fd4e5da5Sopenharmony_ci  // Is the ID the type of a pointer to a storage buffer: BufferBlock-decorated
694fd4e5da5Sopenharmony_ci  // struct in uniform storage class, or Block-decorated struct in StorageBuffer
695fd4e5da5Sopenharmony_ci  // storage class? The result is only valid after internal method
696fd4e5da5Sopenharmony_ci  // CheckDecorationsOfBuffers has been called.
697fd4e5da5Sopenharmony_ci  bool IsPointerToStorageBuffer(uint32_t type_id) const {
698fd4e5da5Sopenharmony_ci    return pointer_to_storage_buffer_.find(type_id) !=
699fd4e5da5Sopenharmony_ci           pointer_to_storage_buffer_.cend();
700fd4e5da5Sopenharmony_ci  }
701fd4e5da5Sopenharmony_ci  // Save the ID of a pointer to a storage buffer.
702fd4e5da5Sopenharmony_ci  void RegisterPointerToStorageBuffer(uint32_t type_id) {
703fd4e5da5Sopenharmony_ci    pointer_to_storage_buffer_.insert(type_id);
704fd4e5da5Sopenharmony_ci  }
705fd4e5da5Sopenharmony_ci  // Is the ID the type of a struct for storage buffer?
706fd4e5da5Sopenharmony_ci  // The result is only valid after internal method CheckDecorationsOfBuffers
707fd4e5da5Sopenharmony_ci  // has been called.
708fd4e5da5Sopenharmony_ci  bool IsStructForStorageBuffer(uint32_t type_id) const {
709fd4e5da5Sopenharmony_ci    return struct_for_storage_buffer_.find(type_id) !=
710fd4e5da5Sopenharmony_ci           struct_for_storage_buffer_.cend();
711fd4e5da5Sopenharmony_ci  }
712fd4e5da5Sopenharmony_ci  // Save the ID of a struct of a storage buffer.
713fd4e5da5Sopenharmony_ci  void RegisterStructForStorageBuffer(uint32_t type_id) {
714fd4e5da5Sopenharmony_ci    struct_for_storage_buffer_.insert(type_id);
715fd4e5da5Sopenharmony_ci  }
716fd4e5da5Sopenharmony_ci
717fd4e5da5Sopenharmony_ci  // Is the ID the type of a pointer to a storage image?  That is, the pointee
718fd4e5da5Sopenharmony_ci  // type is an image type which is known to not use a sampler.
719fd4e5da5Sopenharmony_ci  bool IsPointerToStorageImage(uint32_t type_id) const {
720fd4e5da5Sopenharmony_ci    return pointer_to_storage_image_.find(type_id) !=
721fd4e5da5Sopenharmony_ci           pointer_to_storage_image_.cend();
722fd4e5da5Sopenharmony_ci  }
723fd4e5da5Sopenharmony_ci  // Save the ID of a pointer to a storage image.
724fd4e5da5Sopenharmony_ci  void RegisterPointerToStorageImage(uint32_t type_id) {
725fd4e5da5Sopenharmony_ci    pointer_to_storage_image_.insert(type_id);
726fd4e5da5Sopenharmony_ci  }
727fd4e5da5Sopenharmony_ci
728fd4e5da5Sopenharmony_ci  // Tries to evaluate a 32-bit signed or unsigned scalar integer constant.
729fd4e5da5Sopenharmony_ci  // Returns tuple <is_int32, is_const_int32, value>.
730fd4e5da5Sopenharmony_ci  // OpSpecConstant* return |is_const_int32| as false since their values cannot
731fd4e5da5Sopenharmony_ci  // be relied upon during validation.
732fd4e5da5Sopenharmony_ci  std::tuple<bool, bool, uint32_t> EvalInt32IfConst(uint32_t id) const;
733fd4e5da5Sopenharmony_ci
734fd4e5da5Sopenharmony_ci  // Returns the disassembly string for the given instruction.
735fd4e5da5Sopenharmony_ci  std::string Disassemble(const Instruction& inst) const;
736fd4e5da5Sopenharmony_ci
737fd4e5da5Sopenharmony_ci  // Returns the disassembly string for the given instruction.
738fd4e5da5Sopenharmony_ci  std::string Disassemble(const uint32_t* words, uint16_t num_words) const;
739fd4e5da5Sopenharmony_ci
740fd4e5da5Sopenharmony_ci  // Returns the string name for |decoration|.
741fd4e5da5Sopenharmony_ci  std::string SpvDecorationString(uint32_t decoration) {
742fd4e5da5Sopenharmony_ci    spv_operand_desc desc = nullptr;
743fd4e5da5Sopenharmony_ci    if (grammar_.lookupOperand(SPV_OPERAND_TYPE_DECORATION, decoration,
744fd4e5da5Sopenharmony_ci                               &desc) != SPV_SUCCESS) {
745fd4e5da5Sopenharmony_ci      return std::string("Unknown");
746fd4e5da5Sopenharmony_ci    }
747fd4e5da5Sopenharmony_ci    return std::string(desc->name);
748fd4e5da5Sopenharmony_ci  }
749fd4e5da5Sopenharmony_ci  std::string SpvDecorationString(spv::Decoration decoration) {
750fd4e5da5Sopenharmony_ci    return SpvDecorationString(uint32_t(decoration));
751fd4e5da5Sopenharmony_ci  }
752fd4e5da5Sopenharmony_ci
753fd4e5da5Sopenharmony_ci  // Returns whether type m1 and type m2 are cooperative matrices with
754fd4e5da5Sopenharmony_ci  // the same "shape" (matching scope, rows, cols). If any are specialization
755fd4e5da5Sopenharmony_ci  // constants, we assume they can match because we can't prove they don't.
756fd4e5da5Sopenharmony_ci  spv_result_t CooperativeMatrixShapesMatch(const Instruction* inst,
757fd4e5da5Sopenharmony_ci                                            uint32_t m1, uint32_t m2);
758fd4e5da5Sopenharmony_ci
759fd4e5da5Sopenharmony_ci  // Returns true if |lhs| and |rhs| logically match and, if the decorations of
760fd4e5da5Sopenharmony_ci  // |rhs| are a subset of |lhs|.
761fd4e5da5Sopenharmony_ci  //
762fd4e5da5Sopenharmony_ci  // 1. Must both be either OpTypeArray or OpTypeStruct
763fd4e5da5Sopenharmony_ci  // 2. If OpTypeArray, then
764fd4e5da5Sopenharmony_ci  //  * Length must be the same
765fd4e5da5Sopenharmony_ci  //  * Element type must match or logically match
766fd4e5da5Sopenharmony_ci  // 3. If OpTypeStruct, then
767fd4e5da5Sopenharmony_ci  //  * Both have same number of elements
768fd4e5da5Sopenharmony_ci  //  * Element N for both structs must match or logically match
769fd4e5da5Sopenharmony_ci  //
770fd4e5da5Sopenharmony_ci  // If |check_decorations| is false, then the decorations are not checked.
771fd4e5da5Sopenharmony_ci  bool LogicallyMatch(const Instruction* lhs, const Instruction* rhs,
772fd4e5da5Sopenharmony_ci                      bool check_decorations);
773fd4e5da5Sopenharmony_ci
774fd4e5da5Sopenharmony_ci  // Traces |inst| to find a single base pointer. Returns the base pointer.
775fd4e5da5Sopenharmony_ci  // Will trace through the following instructions:
776fd4e5da5Sopenharmony_ci  // * OpAccessChain
777fd4e5da5Sopenharmony_ci  // * OpInBoundsAccessChain
778fd4e5da5Sopenharmony_ci  // * OpPtrAccessChain
779fd4e5da5Sopenharmony_ci  // * OpInBoundsPtrAccessChain
780fd4e5da5Sopenharmony_ci  // * OpCopyObject
781fd4e5da5Sopenharmony_ci  const Instruction* TracePointer(const Instruction* inst) const;
782fd4e5da5Sopenharmony_ci
783fd4e5da5Sopenharmony_ci  // Validates the storage class for the target environment.
784fd4e5da5Sopenharmony_ci  bool IsValidStorageClass(spv::StorageClass storage_class) const;
785fd4e5da5Sopenharmony_ci
786fd4e5da5Sopenharmony_ci  // Takes a Vulkan Valid Usage ID (VUID) as |id| and optional |reference| and
787fd4e5da5Sopenharmony_ci  // will return a non-empty string only if ID is known and targeting Vulkan.
788fd4e5da5Sopenharmony_ci  // VUIDs are found in the Vulkan-Docs repo in the form "[[VUID-ref-ref-id]]"
789fd4e5da5Sopenharmony_ci  // where "id" is always an 5 char long number (with zeros padding) and matches
790fd4e5da5Sopenharmony_ci  // to |id|. |reference| is used if there is a "common validity" and the VUID
791fd4e5da5Sopenharmony_ci  // shares the same |id| value.
792fd4e5da5Sopenharmony_ci  //
793fd4e5da5Sopenharmony_ci  // More details about Vulkan validation can be found in Vulkan Guide:
794fd4e5da5Sopenharmony_ci  // https://github.com/KhronosGroup/Vulkan-Guide/blob/master/chapters/validation_overview.md
795fd4e5da5Sopenharmony_ci  std::string VkErrorID(uint32_t id, const char* reference = nullptr) const;
796fd4e5da5Sopenharmony_ci
797fd4e5da5Sopenharmony_ci  // Testing method to allow setting the current layout section.
798fd4e5da5Sopenharmony_ci  void SetCurrentLayoutSectionForTesting(ModuleLayoutSection section) {
799fd4e5da5Sopenharmony_ci    current_layout_section_ = section;
800fd4e5da5Sopenharmony_ci  }
801fd4e5da5Sopenharmony_ci
802fd4e5da5Sopenharmony_ci  // Check if instruction 'id' is a consumer of a texture decorated
803fd4e5da5Sopenharmony_ci  // with a QCOM image processing decoration
804fd4e5da5Sopenharmony_ci  bool IsQCOMImageProcessingTextureConsumer(uint32_t id) {
805fd4e5da5Sopenharmony_ci    return qcom_image_processing_consumers_.find(id) !=
806fd4e5da5Sopenharmony_ci           qcom_image_processing_consumers_.end();
807fd4e5da5Sopenharmony_ci  }
808fd4e5da5Sopenharmony_ci
809fd4e5da5Sopenharmony_ci private:
810fd4e5da5Sopenharmony_ci  ValidationState_t(const ValidationState_t&);
811fd4e5da5Sopenharmony_ci
812fd4e5da5Sopenharmony_ci  const spv_const_context context_;
813fd4e5da5Sopenharmony_ci
814fd4e5da5Sopenharmony_ci  /// Stores the Validator command line options. Must be a valid options object.
815fd4e5da5Sopenharmony_ci  const spv_const_validator_options options_;
816fd4e5da5Sopenharmony_ci
817fd4e5da5Sopenharmony_ci  /// The SPIR-V binary module we're validating.
818fd4e5da5Sopenharmony_ci  const uint32_t* words_;
819fd4e5da5Sopenharmony_ci  const size_t num_words_;
820fd4e5da5Sopenharmony_ci
821fd4e5da5Sopenharmony_ci  /// The generator of the SPIR-V.
822fd4e5da5Sopenharmony_ci  uint32_t generator_ = 0;
823fd4e5da5Sopenharmony_ci
824fd4e5da5Sopenharmony_ci  /// The version of the SPIR-V.
825fd4e5da5Sopenharmony_ci  uint32_t version_ = 0;
826fd4e5da5Sopenharmony_ci
827fd4e5da5Sopenharmony_ci  /// The total number of instructions in the binary.
828fd4e5da5Sopenharmony_ci  size_t total_instructions_ = 0;
829fd4e5da5Sopenharmony_ci  /// The total number of functions in the binary.
830fd4e5da5Sopenharmony_ci  size_t total_functions_ = 0;
831fd4e5da5Sopenharmony_ci
832fd4e5da5Sopenharmony_ci  /// IDs which have been forward declared but have not been defined
833fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t> unresolved_forward_ids_;
834fd4e5da5Sopenharmony_ci
835fd4e5da5Sopenharmony_ci  /// IDs that have been declared as forward pointers.
836fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t> forward_pointer_ids_;
837fd4e5da5Sopenharmony_ci
838fd4e5da5Sopenharmony_ci  /// Stores a vector of instructions that use the result of a given
839fd4e5da5Sopenharmony_ci  /// OpSampledImage instruction.
840fd4e5da5Sopenharmony_ci  std::unordered_map<uint32_t, std::vector<Instruction*>>
841fd4e5da5Sopenharmony_ci      sampled_image_consumers_;
842fd4e5da5Sopenharmony_ci
843fd4e5da5Sopenharmony_ci  /// Stores load instructions that load textures used
844fd4e5da5Sopenharmony_ci  //  in QCOM image processing functions
845fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t> qcom_image_processing_consumers_;
846fd4e5da5Sopenharmony_ci
847fd4e5da5Sopenharmony_ci  /// A map of operand IDs and their names defined by the OpName instruction
848fd4e5da5Sopenharmony_ci  std::unordered_map<uint32_t, std::string> operand_names_;
849fd4e5da5Sopenharmony_ci
850fd4e5da5Sopenharmony_ci  /// The section of the code being processed
851fd4e5da5Sopenharmony_ci  ModuleLayoutSection current_layout_section_;
852fd4e5da5Sopenharmony_ci
853fd4e5da5Sopenharmony_ci  /// A list of functions in the module.
854fd4e5da5Sopenharmony_ci  /// Pointers to objects in this container are guaranteed to be stable and
855fd4e5da5Sopenharmony_ci  /// valid until the end of lifetime of the validation state.
856fd4e5da5Sopenharmony_ci  std::vector<Function> module_functions_;
857fd4e5da5Sopenharmony_ci
858fd4e5da5Sopenharmony_ci  /// Capabilities declared in the module
859fd4e5da5Sopenharmony_ci  CapabilitySet module_capabilities_;
860fd4e5da5Sopenharmony_ci
861fd4e5da5Sopenharmony_ci  /// Extensions declared in the module
862fd4e5da5Sopenharmony_ci  ExtensionSet module_extensions_;
863fd4e5da5Sopenharmony_ci
864fd4e5da5Sopenharmony_ci  /// List of all instructions in the order they appear in the binary
865fd4e5da5Sopenharmony_ci  std::vector<Instruction> ordered_instructions_;
866fd4e5da5Sopenharmony_ci
867fd4e5da5Sopenharmony_ci  /// Instructions that can be referenced by Ids
868fd4e5da5Sopenharmony_ci  std::unordered_map<uint32_t, Instruction*> all_definitions_;
869fd4e5da5Sopenharmony_ci
870fd4e5da5Sopenharmony_ci  /// IDs that are entry points, ie, arguments to OpEntryPoint.
871fd4e5da5Sopenharmony_ci  std::vector<uint32_t> entry_points_;
872fd4e5da5Sopenharmony_ci
873fd4e5da5Sopenharmony_ci  /// Maps an entry point id to its descriptions.
874fd4e5da5Sopenharmony_ci  std::unordered_map<uint32_t, std::vector<EntryPointDescription>>
875fd4e5da5Sopenharmony_ci      entry_point_descriptions_;
876fd4e5da5Sopenharmony_ci
877fd4e5da5Sopenharmony_ci  /// IDs that are entry points, ie, arguments to OpEntryPoint, and root a call
878fd4e5da5Sopenharmony_ci  /// graph that recurses.
879fd4e5da5Sopenharmony_ci  std::set<uint32_t> recursive_entry_points_;
880fd4e5da5Sopenharmony_ci
881fd4e5da5Sopenharmony_ci  /// Functions IDs that are target of OpFunctionCall.
882fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t> function_call_targets_;
883fd4e5da5Sopenharmony_ci
884fd4e5da5Sopenharmony_ci  /// ID Bound from the Header
885fd4e5da5Sopenharmony_ci  uint32_t id_bound_;
886fd4e5da5Sopenharmony_ci
887fd4e5da5Sopenharmony_ci  /// Set of Global Variable IDs (Storage Class other than 'Function')
888fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t> global_vars_;
889fd4e5da5Sopenharmony_ci
890fd4e5da5Sopenharmony_ci  /// Set of Local Variable IDs ('Function' Storage Class)
891fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t> local_vars_;
892fd4e5da5Sopenharmony_ci
893fd4e5da5Sopenharmony_ci  /// Set of struct types that have members with a BuiltIn decoration.
894fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t> builtin_structs_;
895fd4e5da5Sopenharmony_ci
896fd4e5da5Sopenharmony_ci  /// Structure Nesting Depth
897fd4e5da5Sopenharmony_ci  std::unordered_map<uint32_t, uint32_t> struct_nesting_depth_;
898fd4e5da5Sopenharmony_ci
899fd4e5da5Sopenharmony_ci  /// Structure has nested blockorbufferblock struct
900fd4e5da5Sopenharmony_ci  std::unordered_map<uint32_t, bool>
901fd4e5da5Sopenharmony_ci      struct_has_nested_blockorbufferblock_struct_;
902fd4e5da5Sopenharmony_ci
903fd4e5da5Sopenharmony_ci  /// Stores the list of decorations for a given <id>
904fd4e5da5Sopenharmony_ci  std::map<uint32_t, std::set<Decoration>> id_decorations_;
905fd4e5da5Sopenharmony_ci
906fd4e5da5Sopenharmony_ci  /// Stores type declarations which need to be unique (i.e. non-aggregates),
907fd4e5da5Sopenharmony_ci  /// in the form [opcode, operand words], result_id is not stored.
908fd4e5da5Sopenharmony_ci  /// Using ordered set to avoid the need for a vector hash function.
909fd4e5da5Sopenharmony_ci  /// The size of this container is expected not to exceed double-digits.
910fd4e5da5Sopenharmony_ci  std::set<std::vector<uint32_t>> unique_type_declarations_;
911fd4e5da5Sopenharmony_ci
912fd4e5da5Sopenharmony_ci  AssemblyGrammar grammar_;
913fd4e5da5Sopenharmony_ci
914fd4e5da5Sopenharmony_ci  spv::AddressingModel addressing_model_;
915fd4e5da5Sopenharmony_ci  spv::MemoryModel memory_model_;
916fd4e5da5Sopenharmony_ci  // pointer size derived from addressing model. Assumes all storage classes
917fd4e5da5Sopenharmony_ci  // have the same pointer size (for physical pointer types).
918fd4e5da5Sopenharmony_ci  uint32_t pointer_size_and_alignment_;
919fd4e5da5Sopenharmony_ci
920fd4e5da5Sopenharmony_ci  /// bit width of sampler/image type variables. Valid values are 32 and 64
921fd4e5da5Sopenharmony_ci  uint32_t sampler_image_addressing_mode_;
922fd4e5da5Sopenharmony_ci
923fd4e5da5Sopenharmony_ci  /// NOTE: See correspoding getter functions
924fd4e5da5Sopenharmony_ci  bool in_function_;
925fd4e5da5Sopenharmony_ci
926fd4e5da5Sopenharmony_ci  /// The state of optional features.  These are determined by capabilities
927fd4e5da5Sopenharmony_ci  /// declared by the module and the environment.
928fd4e5da5Sopenharmony_ci  Feature features_;
929fd4e5da5Sopenharmony_ci
930fd4e5da5Sopenharmony_ci  /// Maps function ids to function stat objects.
931fd4e5da5Sopenharmony_ci  std::unordered_map<uint32_t, Function*> id_to_function_;
932fd4e5da5Sopenharmony_ci
933fd4e5da5Sopenharmony_ci  /// Mapping entry point -> execution models. It is presumed that the same
934fd4e5da5Sopenharmony_ci  /// function could theoretically be used as 'main' by multiple OpEntryPoint
935fd4e5da5Sopenharmony_ci  /// instructions.
936fd4e5da5Sopenharmony_ci  std::unordered_map<uint32_t, std::set<spv::ExecutionModel>>
937fd4e5da5Sopenharmony_ci      entry_point_to_execution_models_;
938fd4e5da5Sopenharmony_ci
939fd4e5da5Sopenharmony_ci  /// Mapping entry point -> execution modes.
940fd4e5da5Sopenharmony_ci  std::unordered_map<uint32_t, std::set<spv::ExecutionMode>>
941fd4e5da5Sopenharmony_ci      entry_point_to_execution_modes_;
942fd4e5da5Sopenharmony_ci
943fd4e5da5Sopenharmony_ci  /// Mapping function -> array of entry points inside this
944fd4e5da5Sopenharmony_ci  /// module which can (indirectly) call the function.
945fd4e5da5Sopenharmony_ci  std::unordered_map<uint32_t, std::vector<uint32_t>> function_to_entry_points_;
946fd4e5da5Sopenharmony_ci  const std::vector<uint32_t> empty_ids_;
947fd4e5da5Sopenharmony_ci
948fd4e5da5Sopenharmony_ci  // The IDs of types of pointers to Block-decorated structs in Uniform storage
949fd4e5da5Sopenharmony_ci  // class. This is populated at the start of ValidateDecorations.
950fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t> pointer_to_uniform_block_;
951fd4e5da5Sopenharmony_ci  // The IDs of struct types for uniform blocks.
952fd4e5da5Sopenharmony_ci  // This is populated at the start of ValidateDecorations.
953fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t> struct_for_uniform_block_;
954fd4e5da5Sopenharmony_ci  // The IDs of types of pointers to BufferBlock-decorated structs in Uniform
955fd4e5da5Sopenharmony_ci  // storage class, or Block-decorated structs in StorageBuffer storage class.
956fd4e5da5Sopenharmony_ci  // This is populated at the start of ValidateDecorations.
957fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t> pointer_to_storage_buffer_;
958fd4e5da5Sopenharmony_ci  // The IDs of struct types for storage buffers.
959fd4e5da5Sopenharmony_ci  // This is populated at the start of ValidateDecorations.
960fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t> struct_for_storage_buffer_;
961fd4e5da5Sopenharmony_ci  // The IDs of types of pointers to storage images.  This is populated in the
962fd4e5da5Sopenharmony_ci  // TypePass.
963fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t> pointer_to_storage_image_;
964fd4e5da5Sopenharmony_ci
965fd4e5da5Sopenharmony_ci  /// Maps ids to friendly names.
966fd4e5da5Sopenharmony_ci  std::unique_ptr<spvtools::FriendlyNameMapper> friendly_mapper_;
967fd4e5da5Sopenharmony_ci  spvtools::NameMapper name_mapper_;
968fd4e5da5Sopenharmony_ci
969fd4e5da5Sopenharmony_ci  /// Variables used to reduce the number of diagnostic messages.
970fd4e5da5Sopenharmony_ci  uint32_t num_of_warnings_;
971fd4e5da5Sopenharmony_ci  uint32_t max_num_of_warnings_;
972fd4e5da5Sopenharmony_ci};
973fd4e5da5Sopenharmony_ci
974fd4e5da5Sopenharmony_ci}  // namespace val
975fd4e5da5Sopenharmony_ci}  // namespace spvtools
976fd4e5da5Sopenharmony_ci
977fd4e5da5Sopenharmony_ci#endif  // SOURCE_VAL_VALIDATION_STATE_H_
978