1 // Copyright (c) 2015-2016 The Khronos Group Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a 4 // copy of this software and/or associated documentation files (the 5 // "Materials"), to deal in the Materials without restriction, including 6 // without limitation the rights to use, copy, modify, merge, publish, 7 // distribute, sublicense, and/or sell copies of the Materials, and to 8 // permit persons to whom the Materials are furnished to do so, subject to 9 // the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included 12 // in all copies or substantial portions of the Materials. 13 // 14 // MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS 15 // KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS 16 // SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT 17 // https://www.khronos.org/registry/ 18 // 19 // THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 26 27 #ifndef LIBSPIRV_VAL_VALIDATIONSTATE_H_ 28 #define LIBSPIRV_VAL_VALIDATIONSTATE_H_ 29 30 #include <list> 31 #include <map> 32 #include <string> 33 #include <unordered_map> 34 #include <unordered_set> 35 #include <vector> 36 37 #include "assembly_grammar.h" 38 #include "diagnostic.h" 39 #include "spirv-tools/libspirv.h" 40 #include "spirv/1.1/spirv.h" 41 #include "spirv_definition.h" 42 43 namespace libspirv { 44 45 // Universal Limit of ResultID + 1 46 static const uint32_t kInvalidId = 0x400000; 47 48 // Info about a result ID. 49 typedef struct spv_id_info_t { 50 /// Id value. 51 uint32_t id; 52 /// Type id, or 0 if no type. 53 uint32_t type_id; 54 /// Opcode of the instruction defining the id. 55 SpvOp opcode; 56 /// Binary words of the instruction defining the id. 57 std::vector<uint32_t> words; 58 } spv_id_info_t; 59 60 /// This enum represents the sections of a SPIRV module. See section 2.4 61 /// of the SPIRV spec for additional details of the order. The enumerant values 62 /// are in the same order as the vector returned by GetModuleOrder 63 enum ModuleLayoutSection { 64 kLayoutCapabilities, /// < Section 2.4 #1 65 kLayoutExtensions, /// < Section 2.4 #2 66 kLayoutExtInstImport, /// < Section 2.4 #3 67 kLayoutMemoryModel, /// < Section 2.4 #4 68 kLayoutEntryPoint, /// < Section 2.4 #5 69 kLayoutExecutionMode, /// < Section 2.4 #6 70 kLayoutDebug1, /// < Section 2.4 #7 > 1 71 kLayoutDebug2, /// < Section 2.4 #7 > 2 72 kLayoutAnnotations, /// < Section 2.4 #8 73 kLayoutTypes, /// < Section 2.4 #9 74 kLayoutFunctionDeclarations, /// < Section 2.4 #10 75 kLayoutFunctionDefinitions /// < Section 2.4 #11 76 }; 77 78 class Function; 79 80 /// This class manages the state of the SPIR-V validation as it is being parsed. 81 class ValidationState_t { 82 public: 83 ValidationState_t(spv_diagnostic* diagnostic, 84 const spv_const_context context); 85 86 /// Forward declares the id in the module 87 spv_result_t ForwardDeclareId(uint32_t id); 88 89 /// Removes a forward declared ID if it has been defined 90 spv_result_t RemoveIfForwardDeclared(uint32_t id); 91 92 /// Assigns a name to an ID 93 void AssignNameToId(uint32_t id, std::string name); 94 95 /// Returns a string representation of the ID in the format <id>[Name] where 96 /// the <id> is the numeric valid of the id and the Name is a name assigned by 97 /// the OpName instruction 98 std::string getIdName(uint32_t id) const; 99 100 /// Like getIdName but does not display the id if the \p id has a name 101 std::string getIdOrName(uint32_t id) const; 102 103 /// Returns the number of ID which have been forward referenced but not 104 /// defined 105 size_t unresolved_forward_id_count() const; 106 107 /// Returns a list of unresolved forward ids. 108 std::vector<uint32_t> UnresolvedForwardIds() const; 109 110 /// Returns true if the id has been defined 111 bool IsDefinedId(uint32_t id) const; 112 113 /// Increments the instruction count. Used for diagnostic 114 int increment_instruction_count(); 115 116 /// Returns the current layout section which is being processed 117 ModuleLayoutSection current_layout_section() const; 118 119 /// Increments the module_layout_order_section_ 120 void ProgressToNextLayoutSectionOrder(); 121 122 /// Determines if the op instruction is part of the current section 123 bool IsOpcodeInCurrentLayoutSection(SpvOp op); 124 125 libspirv::DiagnosticStream diag(spv_result_t error_code) const; 126 127 /// Returns the function states 128 std::list<Function>& functions(); 129 130 /// Returns the function states 131 Function& current_function(); 132 133 /// Returns true if the called after a function instruction but before the 134 /// function end instruction 135 bool in_function_body() const; 136 137 /// Returns true if called after a label instruction but before a branch 138 /// instruction 139 bool in_block() const; 140 141 /// Keeps track of ID definitions and uses. 142 class UseDefTracker { 143 public: 144 void AddDef(const spv_id_info_t& def) { defs_[def.id] = def; } 145 146 void AddUse(uint32_t id) { uses_.insert(id); } 147 148 /// Finds id's def, if it exists. If found, returns <true, def>. Otherwise, 149 /// returns <false, something>. 150 std::pair<bool, spv_id_info_t> FindDef(uint32_t id) const { 151 if (defs_.count(id) == 0) { 152 return std::make_pair(false, spv_id_info_t{}); 153 } else { 154 /// We are in a const function, so we cannot use defs.operator[](). 155 /// Luckily we know the key exists, so defs_.at() won't throw an 156 /// exception. 157 return std::make_pair(true, defs_.at(id)); 158 } 159 } 160 161 /// Returns uses of IDs lacking defs. 162 std::unordered_set<uint32_t> FindUsesWithoutDefs() const { 163 auto diff = uses_; 164 for (const auto d : defs_) diff.erase(d.first); 165 return diff; 166 } 167 168 private: 169 std::unordered_set<uint32_t> uses_; 170 std::unordered_map<uint32_t, spv_id_info_t> defs_; 171 }; 172 173 UseDefTracker& usedefs() { return usedefs_; } 174 const UseDefTracker& usedefs() const { return usedefs_; } 175 176 /// Returns a list of entry point function ids 177 std::vector<uint32_t>& entry_points() { return entry_points_; } 178 const std::vector<uint32_t>& entry_points() const { return entry_points_; } 179 180 /// Registers the capability and its dependent capabilities 181 void RegisterCapability(SpvCapability cap); 182 183 /// Registers the function in the module. Subsequent instructions will be 184 /// called against this function 185 spv_result_t RegisterFunction(uint32_t id, uint32_t ret_type_id, 186 SpvFunctionControlMask function_control, 187 uint32_t function_type_id); 188 189 /// Register a function end instruction 190 spv_result_t RegisterFunctionEnd(); 191 192 /// Returns true if the capability is enabled in the module. 193 bool has_capability(SpvCapability cap) const; 194 195 /// Returns true if any of the capabilities are enabled. Always true for 196 /// capabilities==0. 197 bool HasAnyOf(spv_capability_mask_t capabilities) const; 198 199 /// Sets the addressing model of this module (logical/physical). 200 void set_addressing_model(SpvAddressingModel am); 201 202 /// Returns the addressing model of this module, or Logical if uninitialized. 203 SpvAddressingModel addressing_model() const; 204 205 /// Sets the memory model of this module. 206 void set_memory_model(SpvMemoryModel mm); 207 208 /// Returns the memory model of this module, or Simple if uninitialized. 209 SpvMemoryModel memory_model() const; 210 211 AssemblyGrammar& grammar() { return grammar_; } 212 213 private: 214 spv_diagnostic* diagnostic_; 215 /// Tracks the number of instructions evaluated by the validator 216 int instruction_counter_; 217 218 /// IDs which have been forward declared but have not been defined 219 std::unordered_set<uint32_t> unresolved_forward_ids_; 220 221 /// A map of operand IDs and their names defined by the OpName instruction 222 std::map<uint32_t, std::string> operand_names_; 223 224 /// The section of the code being processed 225 ModuleLayoutSection current_layout_section_; 226 227 /// A list of functions in the module 228 std::list<Function> module_functions_; 229 230 /// Mask of the capabilities available in the module 231 spv_capability_mask_t 232 module_capabilities_; /// Module's declared capabilities. 233 234 /// Definitions and uses of all the IDs in the module. 235 UseDefTracker usedefs_; 236 237 /// IDs that are entry points, ie, arguments to OpEntryPoint. 238 std::vector<uint32_t> entry_points_; 239 240 AssemblyGrammar grammar_; 241 242 SpvAddressingModel addressing_model_; 243 SpvMemoryModel memory_model_; 244 245 /// NOTE: See correspoding getter functions 246 bool in_function_; 247 }; 248 249 } /// namespace libspirv 250 251 #endif /// LIBSPIRV_VAL_VALIDATIONSTATE_H_ 252