diff options
author | Andrey Tuganov <andreyt@google.com> | 2017-11-23 12:11:15 -0500 |
---|---|---|
committer | David Neto <dneto@google.com> | 2017-11-23 23:38:03 -0500 |
commit | 3e08a3f71896c1c15bdcbd42a9ba28ddd0075427 (patch) | |
tree | dd2fc0db90d073dcbb7bdb232cb4219157827156 /source/val | |
parent | d9129f00a57d788a0cbc185b441381f4dfaeaf89 (diff) | |
download | spirv-tools-3e08a3f71896c1c15bdcbd42a9ba28ddd0075427.tar.gz |
Add validation checks for Execution Model
Currently checks that these instructions are called from entry points
with Fragment execution model.
OpImageImplicit*
OpImageQueryLod
OpKill
Diffstat (limited to 'source/val')
-rw-r--r-- | source/val/function.cpp | 22 | ||||
-rw-r--r-- | source/val/function.h | 34 | ||||
-rw-r--r-- | source/val/validation_state.cpp | 8 | ||||
-rw-r--r-- | source/val/validation_state.h | 17 |
4 files changed, 78 insertions, 3 deletions
diff --git a/source/val/function.cpp b/source/val/function.cpp index 91352b2e..d7ac7416 100644 --- a/source/val/function.cpp +++ b/source/val/function.cpp @@ -17,6 +17,7 @@ #include <cassert> #include <algorithm> +#include <sstream> #include <unordered_map> #include <unordered_set> #include <utility> @@ -348,4 +349,25 @@ int Function::GetBlockDepth(BasicBlock* bb) { return block_depth_[bb]; } +bool Function::IsCompatibleWithExecutionModel(SpvExecutionModel model, + std::string* reason) const { + bool is_compatible = true; + std::stringstream ss_reason; + + for (const auto& kv : execution_model_limitations_) { + if (kv.first != model) { + if (!reason) + return false; + is_compatible = false; + ss_reason << kv.second << "\n"; + } + } + + if (!is_compatible && reason) { + *reason = ss_reason.str(); + } + + return is_compatible; +} + } /// namespace libspirv diff --git a/source/val/function.h b/source/val/function.h index f7856b3b..4d53b04f 100644 --- a/source/val/function.h +++ b/source/val/function.h @@ -17,6 +17,8 @@ #include <functional> #include <list> +#include <map> +#include <set> #include <unordered_map> #include <unordered_set> #include <vector> @@ -200,6 +202,30 @@ class Function { /// Prints a directed graph of the CFG of the current funciton void PrintBlocks() const; + /// Registers execution model limitation such as "Feature X is only available + /// with Execution Model Y". Only the first message per model type is + /// registered. + void RegisterExecutionModelLimitation(SpvExecutionModel model, + const std::string& message) { + execution_model_limitations_.emplace(model, message); + } + + /// Returns true if the given execution model passes the limitations stored in + /// execution_model_limitations_. Returns false otherwise and fills optional + /// |reason| parameter. + bool IsCompatibleWithExecutionModel(SpvExecutionModel model, + std::string* reason = nullptr) const; + + // Inserts id to the set of functions called from this function. + void AddFunctionCallTarget(uint32_t call_target_id) { + function_call_targets_.insert(call_target_id); + } + + // Returns a set with ids of all functions called from this function. + const std::set<uint32_t> function_call_targets() const { + return function_call_targets_; + } + private: // Computes the representation of the augmented CFG. // Populates augmented_successors_map_ and augmented_predecessors_map_. @@ -310,6 +336,14 @@ class Function { /// Stores the control flow nesting depth of a given basic block std::unordered_map<BasicBlock*, int> block_depth_; + + /// Stores execution model limitations imposed by instructions used within the + /// function. The string contains message explaining why the limitation was + /// imposed. + std::map<SpvExecutionModel, std::string> execution_model_limitations_; + + /// Stores ids of all functions called from this function. + std::set<uint32_t> function_call_targets_; }; } /// namespace libspirv diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp index cd4dafd5..02b36467 100644 --- a/source/val/validation_state.cpp +++ b/source/val/validation_state.cpp @@ -264,6 +264,13 @@ const Function& ValidationState_t::current_function() const { return module_functions_.back(); } +const Function* ValidationState_t::function(uint32_t id) const { + const auto it = id_to_function_.find(id); + if (it == id_to_function_.end()) + return nullptr; + return it->second; +} + bool ValidationState_t::in_function_body() const { return in_function_; } bool ValidationState_t::in_block() const { @@ -352,6 +359,7 @@ spv_result_t ValidationState_t::RegisterFunction( in_function_ = true; module_functions_.emplace_back(id, ret_type_id, function_control, function_type_id); + id_to_function_.emplace(id, ¤t_function()); // TODO(umar): validate function type and type_id diff --git a/source/val/validation_state.h b/source/val/validation_state.h index 8f261dc8..d57eac7b 100644 --- a/source/val/validation_state.h +++ b/source/val/validation_state.h @@ -140,6 +140,9 @@ class ValidationState_t { Function& current_function(); const Function& current_function() const; + /// Returns function state with the given id, or nullptr if no such function. + const Function* function(uint32_t id) const; + /// Returns true if the called after a function instruction but before the /// function end instruction bool in_function_body() const; @@ -173,6 +176,7 @@ class ValidationState_t { /// Inserts an <id> to the set of functions that are target of OpFunctionCall. void AddFunctionCallTarget(const uint32_t id) { function_call_targets_.insert(id); + current_function().AddFunctionCallTarget(id); } /// Returns whether or not a function<id> is the target of OpFunctionCall. @@ -433,7 +437,9 @@ class ValidationState_t { /// The section of the code being processed ModuleLayoutSection current_layout_section_; - /// A list of functions in the module + /// A list of functions in the module. + /// Pointers to objects in this container are guaranteed to be stable and + /// valid until the end of lifetime of the validation state. std::deque<Function> module_functions_; /// Capabilities declared in the module @@ -443,6 +449,8 @@ class ValidationState_t { libspirv::ExtensionSet module_extensions_; /// List of all instructions in the order they appear in the binary + /// Pointers to objects in this container are guaranteed to be stable and + /// valid until the end of lifetime of the validation state. std::deque<Instruction> ordered_instructions_; /// Instructions that can be referenced by Ids @@ -489,9 +497,12 @@ class ValidationState_t { /// NOTE: See correspoding getter functions bool in_function_; - // The state of optional features. These are determined by capabilities - // declared by the module. + /// The state of optional features. These are determined by capabilities + /// declared by the module. Feature features_; + + /// Maps function ids to function stat objects. + std::unordered_map<uint32_t, Function*> id_to_function_; }; } /// namespace libspirv |