aboutsummaryrefslogtreecommitdiff
path: root/source/validate.h
diff options
context:
space:
mode:
authorUmar Arshad <umar@arrayfire.com>2016-06-02 18:51:05 -0400
committerDavid Neto <dneto@google.com>2016-06-08 14:40:33 -0400
commit90a4252aae7f912345918b48e8b90c03e4c945d4 (patch)
tree72055fa12cbff1f35d061540070d154af3043a4c /source/validate.h
parent00b72c2995736f80c9e14a5a98a9dc613a87c582 (diff)
downloadspirv-tools-90a4252aae7f912345918b48e8b90c03e4c945d4.tar.gz
Split validate_types file into multiple classes
Creates separate files for the ValidationState, Function and BasicBlock classes.
Diffstat (limited to 'source/validate.h')
-rw-r--r--source/validate.h545
1 files changed, 29 insertions, 516 deletions
diff --git a/source/validate.h b/source/validate.h
index 35050cd3..6f2b89e4 100644
--- a/source/validate.h
+++ b/source/validate.h
@@ -44,517 +44,13 @@
#include "spirv-tools/libspirv.h"
#include "spirv_definition.h"
#include "table.h"
-
-#define MSG(msg) \
- do { \
- libspirv::message(__FILE__, size_t(__LINE__), msg); \
- } while (0)
-
-#define SHOW(exp) \
- do { \
- libspirv::message(__FILE__, size_t(__LINE__), #exp, (exp)); \
- } while (0)
+#include "val/BasicBlock.h"
// Structures
-// Info about a result ID.
-typedef struct spv_id_info_t {
- // Id value.
- uint32_t id;
- // Type id, or 0 if no type.
- uint32_t type_id;
- // Opcode of the instruction defining the id.
- SpvOp opcode;
- // Binary words of the instruction defining the id.
- std::vector<uint32_t> words;
-} spv_id_info_t;
-
namespace libspirv {
-void message(std::string file, size_t line, std::string name);
-
-template <typename T>
-void message(std::string file, size_t line, std::string name, T val) {
- std::cout << file << ":" << line << ": " << name << " " << val << std::endl;
-}
-
-/// This enum represents the sections of a SPIRV module. See section 2.4
-/// of the SPIRV spec for additional details of the order. The enumerant values
-/// are in the same order as the vector returned by GetModuleOrder
-enum ModuleLayoutSection {
- kLayoutCapabilities, // < Section 2.4 #1
- kLayoutExtensions, // < Section 2.4 #2
- kLayoutExtInstImport, // < Section 2.4 #3
- kLayoutMemoryModel, // < Section 2.4 #4
- kLayoutEntryPoint, // < Section 2.4 #5
- kLayoutExecutionMode, // < Section 2.4 #6
- kLayoutDebug1, // < Section 2.4 #7 > 1
- kLayoutDebug2, // < Section 2.4 #7 > 2
- kLayoutAnnotations, // < Section 2.4 #8
- kLayoutTypes, // < Section 2.4 #9
- kLayoutFunctionDeclarations, // < Section 2.4 #10
- kLayoutFunctionDefinitions // < Section 2.4 #11
-};
-
-enum class FunctionDecl {
- kFunctionDeclUnknown, // < Unknown function declaration
- kFunctionDeclDeclaration, // < Function declaration
- kFunctionDeclDefinition // < Function definition
-};
-
class ValidationState_t;
-class Function;
-
-// This class represents a basic block in a SPIR-V module
-class BasicBlock {
- public:
- /// Constructor for a BasicBlock
- ///
- /// @param[in] id The ID of the basic block
- explicit BasicBlock(uint32_t id);
-
- /// Returns the id of the BasicBlock
- uint32_t get_id() const { return id_; }
-
- /// Returns the predecessors of the BasicBlock
- const std::vector<BasicBlock*>& get_predecessors() const {
- return predecessors_;
- }
-
- /// Returns the predecessors of the BasicBlock
- std::vector<BasicBlock*>& get_predecessors() { return predecessors_; }
-
- /// Returns the successors of the BasicBlock
- const std::vector<BasicBlock*>& get_successors() const { return successors_; }
-
- /// Returns the successors of the BasicBlock
- std::vector<BasicBlock*>& get_successors() { return successors_; }
-
- /// Returns true if the block should be reachable in the CFG
- bool is_reachable() const { return reachable_; }
-
- void set_reachability(bool reachability) { reachable_ = reachability; }
-
- /// Sets the immedate dominator of this basic block
- ///
- /// @param[in] dom_block The dominator block
- void SetImmediateDominator(BasicBlock* dom_block);
-
- /// Returns the immedate dominator of this basic block
- BasicBlock* GetImmediateDominator();
-
- /// Returns the immedate dominator of this basic block
- const BasicBlock* GetImmediateDominator() const;
-
- /// Ends the block without a successor
- void RegisterBranchInstruction(SpvOp branch_instruction);
-
- /// Adds @p next BasicBlocks as successors of this BasicBlock
- void RegisterSuccessors(std::vector<BasicBlock*> next = {});
-
- /// Returns true if the id of the BasicBlock matches
- bool operator==(const BasicBlock& other) const { return other.id_ == id_; }
-
- /// Returns true if the id of the BasicBlock matches
- bool operator==(const uint32_t& id) const { return id == id_; }
-
- /// @brief A BasicBlock dominator iterator class
- ///
- /// This iterator will iterate over the dominators of the block
- class DominatorIterator
- : public std::iterator<std::forward_iterator_tag, BasicBlock*> {
- public:
- /// @brief Constructs the end of dominator iterator
- ///
- /// This will create an iterator which will represent the element
- /// before the root node of the dominator tree
- DominatorIterator();
-
- /// @brief Constructs an iterator for the given block which points to
- /// @p block
- ///
- /// @param block The block which is referenced by the iterator
- explicit DominatorIterator(const BasicBlock* block);
-
- /// @brief Advances the iterator
- DominatorIterator& operator++();
-
- /// @brief Returns the current element
- const BasicBlock*& operator*();
-
- friend bool operator==(const DominatorIterator& lhs,
- const DominatorIterator& rhs);
-
- private:
- const BasicBlock* current_;
- };
-
- /// Returns an iterator which points to the current block
- const DominatorIterator dom_begin() const;
- DominatorIterator dom_begin();
-
- /// Returns an iterator which points to one element past the first block
- const DominatorIterator dom_end() const;
- DominatorIterator dom_end();
-
- private:
- /// Id of the BasicBlock
- const uint32_t id_;
-
- /// Pointer to the immediate dominator of the BasicBlock
- BasicBlock* immediate_dominator_;
-
- /// The set of predecessors of the BasicBlock
- std::vector<BasicBlock*> predecessors_;
-
- /// The set of successors of the BasicBlock
- std::vector<BasicBlock*> successors_;
-
- SpvOp branch_instruction_;
-
- bool reachable_;
-};
-
-/// @brief Returns true if the iterators point to the same element or if both
-/// iterators point to the @p dom_end block
-bool operator==(const BasicBlock::DominatorIterator& lhs,
- const BasicBlock::DominatorIterator& rhs);
-
-/// @brief Returns true if the iterators point to different elements and they
-/// do not both point to the @p dom_end block
-bool operator!=(const BasicBlock::DominatorIterator& lhs,
- const BasicBlock::DominatorIterator& rhs);
-
-/// @brief This class tracks the CFG constructs as defined in the SPIR-V spec
-class CFConstruct {
- // Universal Limit of ResultID + 1
- static const uint32_t kInitialValue = 0x400000;
-
- public:
- CFConstruct(BasicBlock* header_block, BasicBlock* merge_block,
- BasicBlock* continue_block = nullptr)
- : header_block_(header_block),
- merge_block_(merge_block),
- continue_block_(continue_block) {}
-
- const BasicBlock* get_header() const { return header_block_; }
- const BasicBlock* get_merge() const { return merge_block_; }
- const BasicBlock* get_continue() const { return continue_block_; }
-
- BasicBlock* get_header() { return header_block_; }
- BasicBlock* get_merge() { return merge_block_; }
- BasicBlock* get_continue() { return continue_block_; }
-
- private:
- BasicBlock* header_block_; ///< The header block of a loop or selection
- BasicBlock* merge_block_; ///< The merge block of a loop or selection
- BasicBlock* continue_block_; ///< The continue block of a loop block
-};
-
-// This class manages all function declaration and definitions in a module. It
-// handles the state and id information while parsing a function in the SPIR-V
-// binary.
-class Function {
- public:
- Function(uint32_t id, uint32_t result_type_id,
- SpvFunctionControlMask function_control, uint32_t function_type_id,
- ValidationState_t& module);
-
- /// Registers a function parameter in the current function
- /// @return Returns SPV_SUCCESS if the call was successful
- spv_result_t RegisterFunctionParameter(uint32_t id, uint32_t type_id);
-
- /// Sets the declaration type of the current function
- /// @return Returns SPV_SUCCESS if the call was successful
- spv_result_t RegisterSetFunctionDeclType(FunctionDecl type);
-
- // Registers a block in the current function. Subsequent block instructions
- // will target this block
- // @param id The ID of the label of the block
- /// @return Returns SPV_SUCCESS if the call was successful
- spv_result_t RegisterBlock(uint32_t id, bool is_definition = true);
-
- /// Registers a variable in the current block
- ///
- /// @param[in] type_id The type ID of the varaible
- /// @param[in] id The ID of the varaible
- /// @param[in] storage The storage of the variable
- /// @param[in] init_id The initializer ID of the variable
- ///
- /// @return Returns SPV_SUCCESS if the call was successful
- spv_result_t RegisterBlockVariable(uint32_t type_id, uint32_t id,
- SpvStorageClass storage, uint32_t init_id);
-
- /// Registers a loop merge construct in the function
- ///
- /// @param[in] merge_id The merge block ID of the loop
- /// @param[in] continue_id The continue block ID of the loop
- ///
- /// @return Returns SPV_SUCCESS if the call was successful
- spv_result_t RegisterLoopMerge(uint32_t merge_id, uint32_t continue_id);
-
- /// Registers a selection merge construct in the function
- /// @return Returns SPV_SUCCESS if the call was successful
- spv_result_t RegisterSelectionMerge(uint32_t merge_id);
-
- /// Registers the end of the block
- ///
- /// @param[in] successors_list A list of ids to the blocks successors
- /// @param[in] branch_instruction the branch instruction that ended the block
- void RegisterBlockEnd(std::vector<uint32_t> successors_list,
- SpvOp branch_instruction);
-
- /// Returns true if the \p merge_block_id is a merge block
- bool IsMergeBlock(uint32_t merge_block_id) const;
-
- /// Returns true if the \p id is the first block of this function
- bool IsFirstBlock(uint32_t id) const;
-
- /// Returns the first block of the current function
- const BasicBlock* get_first_block() const;
-
- /// Returns the first block of the current function
- BasicBlock* get_first_block();
-
- /// Returns a vector of all the blocks in the function
- const std::vector<BasicBlock*>& get_blocks() const;
-
- /// Returns a vector of all the blocks in the function
- std::vector<BasicBlock*>& get_blocks();
-
- /// Returns a list of all the cfg constructs in the function
- const std::list<CFConstruct>& get_constructs() const;
-
- /// Returns a list of all the cfg constructs in the function
- std::list<CFConstruct>& get_constructs();
-
- // Returns the number of blocks in the current function being parsed
- size_t get_block_count() const;
-
- /// Returns the id of the funciton
- uint32_t get_id() const { return id_; }
-
- // Returns the number of blocks in the current function being parsed
- size_t get_undefined_block_count() const;
- const std::unordered_set<uint32_t>& get_undefined_blocks() const {
- return undefined_blocks_;
- }
-
- /// Returns the block that is currently being parsed in the binary
- BasicBlock* get_current_block();
-
- /// Returns the block that is currently being parsed in the binary
- const BasicBlock* get_current_block() const;
-
- /// Prints a GraphViz digraph of the CFG of the current funciton
- void printDotGraph() const;
-
- /// Prints a directed graph of the CFG of the current funciton
- void printBlocks() const;
-
- private:
- /// Parent module
- ValidationState_t& module_;
-
- /// The result id of the OpLabel that defined this block
- uint32_t id_;
-
- /// The type of the function
- uint32_t function_type_id_;
-
- /// The type of the return value
- uint32_t result_type_id_;
-
- /// The control fo the funciton
- SpvFunctionControlMask function_control_;
-
- /// The type of declaration of each function
- FunctionDecl declaration_type_;
-
- /// The blocks in the function mapped by block ID
- std::unordered_map<uint32_t, BasicBlock> blocks_;
-
- /// A list of blocks in the order they appeared in the binary
- std::vector<BasicBlock*> ordered_blocks_;
-
- /// Blocks which are forward referenced by blocks but not defined
- std::unordered_set<uint32_t> undefined_blocks_;
-
- /// The block that is currently being parsed
- BasicBlock* current_block_;
-
- /// The constructs that are available in this function
- std::list<CFConstruct> cfg_constructs_;
-
- /// The variable IDs of the functions
- std::vector<uint32_t> variable_ids_;
-
- /// The function parameter ids of the functions
- std::vector<uint32_t> parameter_ids_;
-};
-
-class ValidationState_t {
- public:
- ValidationState_t(spv_diagnostic* diagnostic,
- const spv_const_context context);
-
- // 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;
-
- /// Like getIdName but does not display the id if the \p id has a name
- std::string getIdOrName(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;
-
- // Increments the instruction count. Used for diagnostic
- int incrementInstructionCount();
-
- // Returns the current layout section which is being processed
- ModuleLayoutSection getLayoutSection() const;
-
- // Increments the module_layout_order_section_
- void progressToNextLayoutSectionOrder();
-
- // Determines if the op instruction is part of the current section
- bool isOpcodeInCurrentLayoutSection(SpvOp op);
-
- libspirv::DiagnosticStream diag(spv_result_t error_code) const;
-
- // Returns the function states
- std::list<Function>& get_functions();
-
- // Returns the function states
- Function& get_current_function();
-
- // Returns true if the called after a function instruction but before the
- // function end instruction
- bool in_function_body() const;
-
- // Returns true if called after a label instruction but before a branch
- // instruction
- bool in_block() const;
-
- // Keeps track of ID definitions and uses.
- class UseDefTracker {
- public:
- void AddDef(const spv_id_info_t& def) { defs_[def.id] = def; }
-
- void AddUse(uint32_t id) { uses_.insert(id); }
-
- // Finds id's def, if it exists. If found, returns <true, def>. Otherwise,
- // returns <false, something>.
- std::pair<bool, spv_id_info_t> FindDef(uint32_t id) const {
- if (defs_.count(id) == 0) {
- return std::make_pair(false, spv_id_info_t{});
- } else {
- // We are in a const function, so we cannot use defs.operator[]().
- // Luckily we know the key exists, so defs_.at() won't throw an
- // exception.
- return std::make_pair(true, defs_.at(id));
- }
- }
-
- // Returns uses of IDs lacking defs.
- std::unordered_set<uint32_t> FindUsesWithoutDefs() const {
- auto diff = uses_;
- for (const auto d : defs_) diff.erase(d.first);
- return diff;
- }
-
- private:
- std::unordered_set<uint32_t> uses_;
- std::unordered_map<uint32_t, spv_id_info_t> defs_;
- };
-
- UseDefTracker& usedefs() { return usedefs_; }
- const UseDefTracker& usedefs() const { return usedefs_; }
-
- std::vector<uint32_t>& entry_points() { return entry_points_; }
- const std::vector<uint32_t>& entry_points() const { return entry_points_; }
-
- // Registers the capability and its dependent capabilities
- void RegisterCapability(SpvCapability cap);
-
- // Registers the function in the module. Subsequent instructions will be
- // called against this function
- spv_result_t RegisterFunction(uint32_t id, uint32_t ret_type_id,
- SpvFunctionControlMask function_control,
- uint32_t function_type_id);
-
- // Register a function end instruction
- spv_result_t RegisterFunctionEnd();
-
- // Returns true if the capability is enabled in the module.
- bool hasCapability(SpvCapability cap) const;
-
- // Returns true if any of the capabilities are enabled. Always true for
- // capabilities==0.
- bool HasAnyOf(spv_capability_mask_t capabilities) const;
-
- // Sets the addressing model of this module (logical/physical).
- void setAddressingModel(SpvAddressingModel am);
-
- // Returns the addressing model of this module, or Logical if uninitialized.
- SpvAddressingModel getAddressingModel() const;
-
- // Sets the memory model of this module.
- void setMemoryModel(SpvMemoryModel mm);
-
- // Returns the memory model of this module, or Simple if uninitialized.
- SpvMemoryModel getMemoryModel() const;
-
- AssemblyGrammar& grammar() { return grammar_; }
-
- private:
- spv_diagnostic* diagnostic_;
- // Tracks the number of instructions evaluated by the validator
- int instruction_counter_;
-
- // IDs which have been forward declared but have not been defined
- std::unordered_set<uint32_t> unresolved_forward_ids_;
-
- std::map<uint32_t, std::string> operand_names_;
-
- // The section of the code being processed
- ModuleLayoutSection current_layout_section_;
-
- std::list<Function> module_functions_;
-
- spv_capability_mask_t
- module_capabilities_; // Module's declared capabilities.
-
- // Definitions and uses of all the IDs in the module.
- UseDefTracker usedefs_;
-
- // IDs that are entry points, ie, arguments to OpEntryPoint.
- std::vector<uint32_t> entry_points_;
-
- AssemblyGrammar grammar_;
-
- SpvAddressingModel addressing_model_;
- SpvMemoryModel memory_model_;
-
- // NOTE: See correspoding getter functions
- bool in_function_;
-};
/// @brief Calculates dominator edges of a root basic block
///
@@ -564,7 +60,7 @@ class ValidationState_t {
/// @param[in] first_block the root or entry BasicBlock of a function
///
/// @return a set of dominator edges represented as a pair of blocks
-std::vector<std::pair<BasicBlock*, BasicBlock*> > CalculateDominators(
+std::vector<std::pair<BasicBlock*, BasicBlock*>> CalculateDominators(
const BasicBlock& first_block);
/// @brief Performs the Control Flow Graph checks
@@ -574,20 +70,37 @@ std::vector<std::pair<BasicBlock*, BasicBlock*> > CalculateDominators(
/// @return SPV_SUCCESS if no errors are found. SPV_ERROR_INVALID_CFG otherwise
spv_result_t PerformCfgChecks(ValidationState_t& _);
-// @brief Updates the immediate dominator for each of the block edges
-//
-// Updates the immediate dominator of the blocks for each of the edges
-// provided by the @p dom_edges parameter
-//
-// @param[in,out] dom_edges The edges of the dominator tree
+/// @brief Updates the immediate dominator for each of the block edges
+///
+/// Updates the immediate dominator of the blocks for each of the edges
+/// provided by the @p dom_edges parameter
+///
+/// @param[in,out] dom_edges The edges of the dominator tree
void UpdateImmediateDominators(
- std::vector<std::pair<BasicBlock*, BasicBlock*> >& dom_edges);
+ std::vector<std::pair<BasicBlock*, BasicBlock*>>& dom_edges);
-// @brief Prints all of the dominators of a BasicBlock
-//
-// @param[in] block The dominators of this block will be printed
+/// @brief Prints all of the dominators of a BasicBlock
+///
+/// @param[in] block The dominators of this block will be printed
void printDominatorList(BasicBlock& block);
+/// Performs logical layout validation as described in section 2.4 of the SPIR-V
+/// spec.
+spv_result_t ModuleLayoutPass(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst);
+
+/// Performs Control Flow Graph validation of a module
+spv_result_t CfgPass(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst);
+
+/// Performs SSA validation of a module
+spv_result_t SsaPass(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst);
+
+/// Performs instruction validation.
+spv_result_t InstructionPass(ValidationState_t& _,
+ const spv_parsed_instruction_t* inst);
+
} // namespace libspirv
/// @brief Validate the ID usage of the instruction stream