aboutsummaryrefslogtreecommitdiff
path: root/source/val
diff options
context:
space:
mode:
authorAlan Baker <alanbaker@google.com>2018-04-16 13:58:11 -0400
committerDavid Neto <dneto@google.com>2018-04-17 10:26:38 -0400
commit38359ba80006569e540035133852122e348201e1 (patch)
treed16f537f0a66f1b69c2dc927d32e1c50ad64023e /source/val
parent152b9a681ebec0aab3f3d83c7b775e2dc2e1df36 (diff)
downloadspirv-tools-38359ba80006569e540035133852122e348201e1.tar.gz
Fixes #1483. Validating Vulkan 1.1 barrier execution scopes
* Reworked how execution model limitations are checked * Now OpFunction checks which entry points call it and checks its registered limitations instead of building a call stack in the entry point * New tests * Moving function to entry point mapping into VState
Diffstat (limited to 'source/val')
-rw-r--r--source/val/validation_state.cpp34
-rw-r--r--source/val/validation_state.h12
2 files changed, 46 insertions, 0 deletions
diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp
index 50ebb622..c10c84ed 100644
--- a/source/val/validation_state.cpp
+++ b/source/val/validation_state.cpp
@@ -15,6 +15,7 @@
#include "val/validation_state.h"
#include <cassert>
+#include <stack>
#include "opcode.h"
#include "val/basic_block.h"
@@ -792,4 +793,37 @@ std::tuple<bool, bool, uint32_t> ValidationState_t::EvalInt32IfConst(
return std::make_tuple(true, true, inst->word(3));
}
+void ValidationState_t::ComputeFunctionToEntryPointMapping() {
+ for (const uint32_t entry_point : entry_points()) {
+ std::stack<uint32_t> call_stack;
+ std::set<uint32_t> visited;
+ call_stack.push(entry_point);
+ while (!call_stack.empty()) {
+ const uint32_t called_func_id = call_stack.top();
+ call_stack.pop();
+ if (!visited.insert(called_func_id).second) continue;
+
+ function_to_entry_points_[called_func_id].push_back(entry_point);
+
+ const Function* called_func = function(called_func_id);
+ if (called_func) {
+ // Other checks should error out on this invalid SPIR-V.
+ for (const uint32_t new_call : called_func->function_call_targets()) {
+ call_stack.push(new_call);
+ }
+ }
+ }
+ }
+}
+
+const std::vector<uint32_t>& ValidationState_t::FunctionEntryPoints(
+ uint32_t func) const {
+ auto iter = function_to_entry_points_.find(func);
+ if (iter == function_to_entry_points_.end()) {
+ return empty_ids_;
+ } else {
+ return iter->second;
+ }
+}
+
} // namespace libspirv
diff --git a/source/val/validation_state.h b/source/val/validation_state.h
index 3e382c80..ade5da1a 100644
--- a/source/val/validation_state.h
+++ b/source/val/validation_state.h
@@ -208,6 +208,13 @@ class ValidationState_t {
return &it->second;
}
+ /// Traverses call tree and computes function_to_entry_points_.
+ /// Note: called after fully parsing the binary.
+ void ComputeFunctionToEntryPointMapping();
+
+ /// Returns all the entry points that can call |func|.
+ const std::vector<uint32_t>& FunctionEntryPoints(uint32_t func) const;
+
/// Inserts an <id> to the set of functions that are target of OpFunctionCall.
void AddFunctionCallTarget(const uint32_t id) {
function_call_targets_.insert(id);
@@ -559,6 +566,11 @@ class ValidationState_t {
/// Mapping entry point -> execution modes.
std::unordered_map<uint32_t, std::set<SpvExecutionMode>>
entry_point_to_execution_modes_;
+
+ /// Mapping function -> array of entry points inside this
+ /// module which can (indirectly) call the function.
+ std::unordered_map<uint32_t, std::vector<uint32_t>> function_to_entry_points_;
+ const std::vector<uint32_t> empty_ids_;
};
} // namespace libspirv