From 6d37e3c5f330ae4dbdad6c140ee84af94f941489 Mon Sep 17 00:00:00 2001 From: Umar Arshad Date: Mon, 14 Dec 2015 08:21:08 -0500 Subject: [PATCH] Refactor validation types into another file --- CMakeLists.txt | 2 + include/libspirv/libspirv.h | 1 + source/validate.cpp | 88 ++---------------------------- source/validate_types.cpp | 105 ++++++++++++++++++++++++++++++++++++ source/validate_types.h | 98 +++++++++++++++++++++++++++++++++ test/ValidateFixtures.cpp | 2 + test/ValidateFixtures.h | 4 ++ 7 files changed, 215 insertions(+), 85 deletions(-) create mode 100644 source/validate_types.cpp create mode 100644 source/validate_types.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a0fc77ca..4b74257c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,6 +115,7 @@ set(SPIRV_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/source/text.h ${CMAKE_CURRENT_SOURCE_DIR}/source/text_handler.h ${CMAKE_CURRENT_SOURCE_DIR}/source/validate.h + ${CMAKE_CURRENT_SOURCE_DIR}/source/validate_types.h ${CMAKE_CURRENT_SOURCE_DIR}/source/assembly_grammar.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/binary.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/disassemble.cpp @@ -128,6 +129,7 @@ set(SPIRV_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/source/text.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/text_handler.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/validate.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/source/validate_types.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/validate_id.cpp) add_library(${SPIRV_TOOLS} ${SPIRV_SOURCES}) diff --git a/include/libspirv/libspirv.h b/include/libspirv/libspirv.h index 07bbe75e..bd5ad5af 100644 --- a/include/libspirv/libspirv.h +++ b/include/libspirv/libspirv.h @@ -74,6 +74,7 @@ typedef enum spv_result_t { SPV_ERROR_INVALID_DIAGNOSTIC = -8, SPV_ERROR_INVALID_LOOKUP = -9, SPV_ERROR_INVALID_ID = -10, + SPV_ERROR_INVALID_CFG = -11, SPV_FORCE_32_BIT_ENUM(spv_result_t) } spv_result_t; diff --git a/source/validate.cpp b/source/validate.cpp index 4554e014..179d225f 100644 --- a/source/validate.cpp +++ b/source/validate.cpp @@ -25,6 +25,7 @@ // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. #include "validate.h" +#include "validate_types.h" #include "binary.h" #include "diagnostic.h" @@ -56,6 +57,7 @@ using std::transform; using std::unordered_set; using std::vector; +using libspirv::ValidationState_t; #define spvCheckReturn(expression) \ if (spv_result_t error = (expression)) return error; @@ -303,90 +305,6 @@ spv_result_t setHeader(void* user_data, spv_endianness_t endian, uint32_t magic, return SPV_SUCCESS; } -// TODO(umar): Move this class to another file -class ValidationState_t { - public: - ValidationState_t(spv_diagnostic* diag, uint32_t options) - : diagnostic_(diag), - instruction_counter_(0), - validation_flags_(options) {} - - spv_result_t definedIds(uint32_t id) { - if (defined_ids_.find(id) == std::end(defined_ids_)) { - defined_ids_.insert(id); - } else { - return diag(SPV_ERROR_INVALID_ID) - << "ID cannot be assigned multiple times"; - } - return SPV_SUCCESS; - } - - spv_result_t forwardDeclareId(uint32_t id) { - unresolved_forward_ids_.insert(id); - return SPV_SUCCESS; - } - - spv_result_t removeIfForwardDeclared(uint32_t id) { - unresolved_forward_ids_.erase(id); - return SPV_SUCCESS; - } - - void assignNameToId(uint32_t id, string name) { operand_names[id] = name; } - - string getIdName(uint32_t id) { - std::stringstream out; - out << id; - if (operand_names.find(id) != end(operand_names)) { - out << "[" << operand_names[id] << "]"; - } - return out.str(); - } - - size_t unresolvedForwardIdCount() const { - return unresolved_forward_ids_.size(); - } - - vector unresolvedForwardIds() const { - vector out(begin(unresolved_forward_ids_), - end(unresolved_forward_ids_)); - return out; - } - - // - bool isDefinedId(uint32_t id) const { - return defined_ids_.find(id) != std::end(defined_ids_); - } - - bool is_enabled(uint32_t flag) const { - return (flag & validation_flags_) == flag; - } - - // Increments the instruction count. Used for diagnostic - int incrementInstructionCount() { return instruction_counter_++; } - - libspirv::DiagnosticStream diag(spv_result_t error_code) const { - return libspirv::DiagnosticStream( - {0, 0, static_cast(instruction_counter_)}, diagnostic_, - error_code); - } - - private: - spv_diagnostic* diagnostic_; - // Tracks the number of instructions evaluated by the validator - int instruction_counter_; - - // All IDs which have been defined - unordered_set defined_ids_; - - // IDs which have been forward declared but have not been defined - unordered_set unresolved_forward_ids_; - - // Validation options to determine the passes to execute - uint32_t validation_flags_; - - map operand_names; -}; - // Performs SSA validation on the IDs of an instruction. The // can_have_forward_declared_ids functor should return true if the // instruction operand's ID can be forward referenced. @@ -407,7 +325,7 @@ spv_result_t SsaPass(ValidationState_t& _, switch (type) { case SPV_OPERAND_TYPE_RESULT_ID: _.removeIfForwardDeclared(*operand_ptr); - ret = _.definedIds(*operand_ptr); + ret = _.defineId(*operand_ptr); break; case SPV_OPERAND_TYPE_ID: case SPV_OPERAND_TYPE_TYPE_ID: diff --git a/source/validate_types.cpp b/source/validate_types.cpp new file mode 100644 index 00000000..0779b2e4 --- /dev/null +++ b/source/validate_types.cpp @@ -0,0 +1,105 @@ +// Copyright (c) 2015 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + +#include "validate_types.h" + +#include +#include +#include +#include + +using std::string; +using std::vector; +using std::unordered_set; + +namespace libspirv { + +ValidationState_t::ValidationState_t(spv_diagnostic* diag, uint32_t options) + : diagnostic_(diag), instruction_counter_(0), validation_flags_(options) {} + +spv_result_t ValidationState_t::defineId(uint32_t id) { + if (defined_ids_.find(id) == end(defined_ids_)) { + defined_ids_.insert(id); + } else { + return diag(SPV_ERROR_INVALID_ID) << "ID cannot be assigned multiple times"; + } + return SPV_SUCCESS; +} + +spv_result_t ValidationState_t::forwardDeclareId(uint32_t id) { + unresolved_forward_ids_.insert(id); + return SPV_SUCCESS; +} + +spv_result_t ValidationState_t::removeIfForwardDeclared(uint32_t id) { + unresolved_forward_ids_.erase(id); + return SPV_SUCCESS; +} + +void ValidationState_t::assignNameToId(uint32_t id, string name) { + operand_names_[id] = name; +} + +string ValidationState_t::getIdName(uint32_t id) const { + std::stringstream out; + out << id; + if (operand_names_.find(id) != end(operand_names_)) { + out << "[" << operand_names_.at(id) << "]"; + } + return out.str(); +} + +size_t ValidationState_t::unresolvedForwardIdCount() const { + return unresolved_forward_ids_.size(); +} + +vector ValidationState_t::unresolvedForwardIds() const { + vector out(begin(unresolved_forward_ids_), + end(unresolved_forward_ids_)); + return out; +} + +// +bool ValidationState_t::isDefinedId(uint32_t id) const { + return defined_ids_.find(id) != end(defined_ids_); +} + +bool ValidationState_t::is_enabled(spv_validate_options_t flag) const { + return (flag & validation_flags_) == flag; +} + +// Increments the instruction count. Used for diagnostic +int ValidationState_t::incrementInstructionCount() { + return instruction_counter_++; +} + +libspirv::DiagnosticStream ValidationState_t::diag( + spv_result_t error_code) const { + return libspirv::DiagnosticStream( + {0, 0, static_cast(instruction_counter_)}, diagnostic_, + error_code); +} +} diff --git a/source/validate_types.h b/source/validate_types.h new file mode 100644 index 00000000..add6b295 --- /dev/null +++ b/source/validate_types.h @@ -0,0 +1,98 @@ +// Copyright (c) 2015 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and/or associated documentation files (the +// "Materials"), to deal in the Materials without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Materials, and to +// permit persons to whom the Materials are furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Materials. +// +// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS +// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS +// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT +// https://www.khronos.org/registry/ +// +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + +#ifndef LIBSPIRV_VALIDATE_TYPES_H_ +#define LIBSPIRV_VALIDATE_TYPES_H_ + +#include "binary.h" +#include "diagnostic.h" +#include "libspirv/libspirv.h" + +#include +#include +#include +#include + +namespace libspirv { + +class ValidationState_t { + public: + ValidationState_t(spv_diagnostic* diag, uint32_t options); + + // Defines the \p id for the module + spv_result_t defineId(uint32_t id); + + // Forward declares the id in the module + spv_result_t forwardDeclareId(uint32_t id); + + // Removes a forward declared ID if it has been defined + spv_result_t removeIfForwardDeclared(uint32_t id); + + // Assigns a name to an ID + void assignNameToId(uint32_t id, std::string name); + + // Returns a string representation of the ID in the format [Name] where + // the is the numeric valid of the id and the Name is a name assigned by + // the OpName instruction + std::string getIdName(uint32_t id) const; + + // Returns the number of ID which have been forward referenced but not defined + size_t unresolvedForwardIdCount() const; + + // Returns a list of unresolved forward ids. + std::vector unresolvedForwardIds() const; + + // Returns true if the id has been defined + bool isDefinedId(uint32_t id) const; + + // Returns true if an spv_validate_options_t option is enabled in the + // validation instruction + bool is_enabled(spv_validate_options_t flag) const; + + // Increments the instruction count. Used for diagnostic + int incrementInstructionCount(); + + libspirv::DiagnosticStream diag(spv_result_t error_code) const; + + private: + spv_diagnostic* diagnostic_; + // Tracks the number of instructions evaluated by the validator + int instruction_counter_; + + // All IDs which have been defined + std::unordered_set defined_ids_; + + // IDs which have been forward declared but have not been defined + std::unordered_set unresolved_forward_ids_; + + // Validation options to determine the passes to execute + uint32_t validation_flags_; + + std::map operand_names_; +}; +} + +#endif diff --git a/test/ValidateFixtures.cpp b/test/ValidateFixtures.cpp index 5fde6209..284fefe5 100644 --- a/test/ValidateFixtures.cpp +++ b/test/ValidateFixtures.cpp @@ -75,4 +75,6 @@ std::string ValidateBase::getDiagnosticString() { template class spvtest::ValidateBase, SPV_VALIDATE_SSA_BIT>; +template class spvtest::ValidateBase; } diff --git a/test/ValidateFixtures.h b/test/ValidateFixtures.h index 1978f877..dbd35000 100644 --- a/test/ValidateFixtures.h +++ b/test/ValidateFixtures.h @@ -26,6 +26,9 @@ // Common validation fixtures for unit tests +#ifndef LIBSPIRV_TEST_VALIDATE_FIXTURES_H_ +#define LIBSPIRV_TEST_VALIDATE_FIXTURES_H_ + #include "UnitSPIRV.h" namespace spvtest { @@ -56,3 +59,4 @@ class ValidateBase : public ::testing::Test, static const uint32_t validation_options_ = OPTIONS; }; } +#endif