Refactor validation types into another file

This commit is contained in:
Umar Arshad 2015-12-14 08:21:08 -05:00 committed by David Neto
parent 532af9c09c
commit 6d37e3c5f3
7 changed files with 215 additions and 85 deletions

View File

@ -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})

View File

@ -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;

View File

@ -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<uint32_t> unresolvedForwardIds() const {
vector<uint32_t> 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<size_t>(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<uint32_t> defined_ids_;
// IDs which have been forward declared but have not been defined
unordered_set<uint32_t> unresolved_forward_ids_;
// Validation options to determine the passes to execute
uint32_t validation_flags_;
map<uint32_t, string> 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:

105
source/validate_types.cpp Normal file
View File

@ -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 <map>
#include <string>
#include <unordered_set>
#include <vector>
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<uint32_t> ValidationState_t::unresolvedForwardIds() const {
vector<uint32_t> 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<size_t>(instruction_counter_)}, diagnostic_,
error_code);
}
}

98
source/validate_types.h Normal file
View File

@ -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 <map>
#include <string>
#include <unordered_set>
#include <vector>
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 <id>[Name] where
// the <id> 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<uint32_t> 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<uint32_t> defined_ids_;
// IDs which have been forward declared but have not been defined
std::unordered_set<uint32_t> unresolved_forward_ids_;
// Validation options to determine the passes to execute
uint32_t validation_flags_;
std::map<uint32_t, std::string> operand_names_;
};
}
#endif

View File

@ -75,4 +75,6 @@ std::string ValidateBase<T, OPTIONS>::getDiagnosticString() {
template class spvtest::ValidateBase<std::pair<std::string, bool>,
SPV_VALIDATE_SSA_BIT>;
template class spvtest::ValidateBase<bool,
SPV_VALIDATE_SSA_BIT>;
}

View File

@ -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