aboutsummaryrefslogtreecommitdiff
path: root/source/val
diff options
context:
space:
mode:
authorAndrey Tuganov <andreyt@google.com>2017-11-23 12:11:15 -0500
committerDavid Neto <dneto@google.com>2017-11-23 23:38:03 -0500
commit3e08a3f71896c1c15bdcbd42a9ba28ddd0075427 (patch)
treedd2fc0db90d073dcbb7bdb232cb4219157827156 /source/val
parentd9129f00a57d788a0cbc185b441381f4dfaeaf89 (diff)
downloadspirv-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.cpp22
-rw-r--r--source/val/function.h34
-rw-r--r--source/val/validation_state.cpp8
-rw-r--r--source/val/validation_state.h17
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, &current_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