diff options
author | Alan Baker <alanbaker@google.com> | 2018-04-16 13:58:11 -0400 |
---|---|---|
committer | David Neto <dneto@google.com> | 2018-04-17 10:26:38 -0400 |
commit | 38359ba80006569e540035133852122e348201e1 (patch) | |
tree | d16f537f0a66f1b69c2dc927d32e1c50ad64023e /source/val | |
parent | 152b9a681ebec0aab3f3d83c7b775e2dc2e1df36 (diff) | |
download | spirv-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.cpp | 34 | ||||
-rw-r--r-- | source/val/validation_state.h | 12 |
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 |