SPIRV-Tools/source/val/ValidationState.h
Lei Zhang 755f97f534 Add a callback mechanism for communicating messages to callers.
Every time an event happens in the library that the user should be
aware of, the callback will be invoked.

The existing diagnostic mechanism is hijacked internally by a
callback that creates an diagnostic object each time an event
happens.
2016-09-15 12:35:48 -04:00

221 lines
7.5 KiB
C++

// Copyright (c) 2015-2016 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LIBSPIRV_VAL_VALIDATIONSTATE_H_
#define LIBSPIRV_VAL_VALIDATIONSTATE_H_
#include <deque>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "assembly_grammar.h"
#include "diagnostic.h"
#include "enum_set.h"
#include "spirv-tools/libspirv.h"
#include "spirv/1.1/spirv.h"
#include "spirv_definition.h"
#include "val/Function.h"
#include "val/Instruction.h"
namespace libspirv {
/// 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
};
/// This class manages the state of the SPIR-V validation as it is being parsed.
class ValidationState_t {
public:
ValidationState_t(const spv_const_context context);
/// Returns the context
spv_const_context context() const { return 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 unresolved_forward_id_count() const;
/// Returns a vector 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 increment_instruction_count();
/// Returns the current layout section which is being processed
ModuleLayoutSection current_layout_section() 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::deque<Function>& functions();
/// Returns the function states
Function& 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;
/// Returns a list of entry point function ids
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 {
return module_capabilities_.Contains(cap);
}
/// Returns true if any of the capabilities are enabled, or if the given
/// capabilities is the empty set.
bool HasAnyOf(const libspirv::CapabilitySet& capabilities) const;
/// Sets the addressing model of this module (logical/physical).
void set_addressing_model(SpvAddressingModel am);
/// Returns the addressing model of this module, or Logical if uninitialized.
SpvAddressingModel addressing_model() const;
/// Sets the memory model of this module.
void set_memory_model(SpvMemoryModel mm);
/// Returns the memory model of this module, or Simple if uninitialized.
SpvMemoryModel memory_model() const;
AssemblyGrammar& grammar() { return grammar_; }
/// Registers the instruction
void RegisterInstruction(const spv_parsed_instruction_t& inst);
/// Finds id's def, if it exists. If found, returns the definition otherwise
/// nullptr
const Instruction* FindDef(uint32_t id) const;
/// Finds id's def, if it exists. If found, returns the definition otherwise
/// nullptr
Instruction* FindDef(uint32_t id);
/// Returns a deque of instructions in the order they appear in the binary
const std::deque<Instruction>& ordered_instructions() {
return ordered_instructions_;
}
/// Returns a map of instructions mapped by their result id
const std::unordered_map<uint32_t, Instruction*>& all_definitions() const {
return all_definitions_;
}
private:
ValidationState_t(const ValidationState_t&);
const spv_const_context context_;
/// 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_;
/// A map of operand IDs and their names defined by the OpName instruction
std::unordered_map<uint32_t, std::string> operand_names_;
/// The section of the code being processed
ModuleLayoutSection current_layout_section_;
/// A list of functions in the module
std::deque<Function> module_functions_;
/// The capabilities available in the module
libspirv::CapabilitySet
module_capabilities_; /// Module's declared capabilities.
/// List of all instructions in the order they appear in the binary
std::deque<Instruction> ordered_instructions_;
/// Instructions that can be referenced by Ids
std::unordered_map<uint32_t, Instruction*> all_definitions_;
/// 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_;
};
} /// namespace libspirv
#endif /// LIBSPIRV_VAL_VALIDATIONSTATE_H_