mirror of
https://github.com/xenia-project/SPIRV-Tools.git
synced 2024-11-23 11:19:41 +00:00
Fix several violations of the style guide
This commit is contained in:
parent
3df8f7cebd
commit
886dd352d5
@ -33,8 +33,8 @@ using std::vector;
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
BasicBlock::BasicBlock(uint32_t id)
|
||||
: id_(id),
|
||||
BasicBlock::BasicBlock(uint32_t label_id)
|
||||
: id_(label_id),
|
||||
immediate_dominator_(nullptr),
|
||||
immediate_post_dominator_(nullptr),
|
||||
predecessors_(),
|
||||
@ -50,16 +50,16 @@ void BasicBlock::SetImmediatePostDominator(BasicBlock* pdom_block) {
|
||||
immediate_post_dominator_ = pdom_block;
|
||||
}
|
||||
|
||||
const BasicBlock* BasicBlock::GetImmediateDominator() const {
|
||||
const BasicBlock* BasicBlock::immediate_dominator() const {
|
||||
return immediate_dominator_;
|
||||
}
|
||||
|
||||
const BasicBlock* BasicBlock::GetImmediatePostDominator() const {
|
||||
const BasicBlock* BasicBlock::immediate_post_dominator() const {
|
||||
return immediate_post_dominator_;
|
||||
}
|
||||
|
||||
BasicBlock* BasicBlock::GetImmediateDominator() { return immediate_dominator_; }
|
||||
BasicBlock* BasicBlock::GetImmediatePostDominator() {
|
||||
BasicBlock* BasicBlock::immediate_dominator() { return immediate_dominator_; }
|
||||
BasicBlock* BasicBlock::immediate_post_dominator() {
|
||||
return immediate_post_dominator_;
|
||||
}
|
||||
|
||||
@ -102,12 +102,12 @@ BasicBlock::DominatorIterator& BasicBlock::DominatorIterator::operator++() {
|
||||
|
||||
const BasicBlock::DominatorIterator BasicBlock::dom_begin() const {
|
||||
return DominatorIterator(
|
||||
this, [](const BasicBlock* b) { return b->GetImmediateDominator(); });
|
||||
this, [](const BasicBlock* b) { return b->immediate_dominator(); });
|
||||
}
|
||||
|
||||
BasicBlock::DominatorIterator BasicBlock::dom_begin() {
|
||||
return DominatorIterator(
|
||||
this, [](const BasicBlock* b) { return b->GetImmediateDominator(); });
|
||||
this, [](const BasicBlock* b) { return b->immediate_dominator(); });
|
||||
}
|
||||
|
||||
const BasicBlock::DominatorIterator BasicBlock::dom_end() const {
|
||||
@ -120,12 +120,12 @@ BasicBlock::DominatorIterator BasicBlock::dom_end() {
|
||||
|
||||
const BasicBlock::DominatorIterator BasicBlock::pdom_begin() const {
|
||||
return DominatorIterator(
|
||||
this, [](const BasicBlock* b) { return b->GetImmediatePostDominator(); });
|
||||
this, [](const BasicBlock* b) { return b->immediate_post_dominator(); });
|
||||
}
|
||||
|
||||
BasicBlock::DominatorIterator BasicBlock::pdom_begin() {
|
||||
return DominatorIterator(
|
||||
this, [](const BasicBlock* b) { return b->GetImmediatePostDominator(); });
|
||||
this, [](const BasicBlock* b) { return b->immediate_post_dominator(); });
|
||||
}
|
||||
|
||||
const BasicBlock::DominatorIterator BasicBlock::pdom_end() const {
|
||||
|
@ -57,26 +57,24 @@ class BasicBlock {
|
||||
explicit BasicBlock(uint32_t id);
|
||||
|
||||
/// Returns the id of the BasicBlock
|
||||
uint32_t get_id() const { return id_; }
|
||||
uint32_t id() const { return id_; }
|
||||
|
||||
/// Returns the predecessors of the BasicBlock
|
||||
const std::vector<BasicBlock*>* get_predecessors() const {
|
||||
const std::vector<BasicBlock*>* predecessors() const {
|
||||
return &predecessors_;
|
||||
}
|
||||
|
||||
/// Returns the predecessors of the BasicBlock
|
||||
std::vector<BasicBlock*>* get_predecessors() { return &predecessors_; }
|
||||
std::vector<BasicBlock*>* predecessors() { return &predecessors_; }
|
||||
|
||||
/// Returns the successors of the BasicBlock
|
||||
const std::vector<BasicBlock*>* get_successors() const {
|
||||
return &successors_;
|
||||
}
|
||||
const std::vector<BasicBlock*>* successors() const { return &successors_; }
|
||||
|
||||
/// Returns the successors of the BasicBlock
|
||||
std::vector<BasicBlock*>* get_successors() { return &successors_; }
|
||||
std::vector<BasicBlock*>* successors() { return &successors_; }
|
||||
|
||||
/// Returns true if the block is reachable in the CFG
|
||||
bool is_reachable() const { return reachable_; }
|
||||
bool reachable() const { return reachable_; }
|
||||
|
||||
/// Returns true if BasicBlock is of the given type
|
||||
bool is_type(BlockType type) const {
|
||||
@ -106,16 +104,16 @@ class BasicBlock {
|
||||
void SetImmediatePostDominator(BasicBlock* pdom_block);
|
||||
|
||||
/// Returns the immedate dominator of this basic block
|
||||
BasicBlock* GetImmediateDominator();
|
||||
BasicBlock* immediate_dominator();
|
||||
|
||||
/// Returns the immedate dominator of this basic block
|
||||
const BasicBlock* GetImmediateDominator() const;
|
||||
const BasicBlock* immediate_dominator() const;
|
||||
|
||||
/// Returns the immedate post dominator of this basic block
|
||||
BasicBlock* GetImmediatePostDominator();
|
||||
BasicBlock* immediate_post_dominator();
|
||||
|
||||
/// Returns the immedate post dominator of this basic block
|
||||
const BasicBlock* GetImmediatePostDominator() const;
|
||||
const BasicBlock* immediate_post_dominator() const;
|
||||
|
||||
/// Ends the block without a successor
|
||||
void RegisterBranchInstruction(SpvOp branch_instruction);
|
||||
@ -135,7 +133,7 @@ class BasicBlock {
|
||||
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_; }
|
||||
bool operator==(const uint32_t& other_id) const { return other_id == id_; }
|
||||
|
||||
/// @brief A BasicBlock dominator iterator class
|
||||
///
|
||||
|
@ -31,19 +31,20 @@
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
Construct::Construct(ConstructType type, BasicBlock* entry,
|
||||
BasicBlock* exit, std::vector<Construct*> constructs)
|
||||
: type_(type),
|
||||
Construct::Construct(ConstructType construct_type,
|
||||
BasicBlock* entry, BasicBlock* exit,
|
||||
std::vector<Construct*> constructs)
|
||||
: type_(construct_type),
|
||||
corresponding_constructs_(constructs),
|
||||
entry_block_(entry),
|
||||
exit_block_(exit) {}
|
||||
|
||||
ConstructType Construct::get_type() const { return type_; }
|
||||
ConstructType Construct::type() const { return type_; }
|
||||
|
||||
const std::vector<Construct*>& Construct::get_corresponding_constructs() const {
|
||||
const std::vector<Construct*>& Construct::corresponding_constructs() const {
|
||||
return corresponding_constructs_;
|
||||
}
|
||||
std::vector<Construct*>& Construct::get_corresponding_constructs() {
|
||||
std::vector<Construct*>& Construct::corresponding_constructs() {
|
||||
return corresponding_constructs_;
|
||||
}
|
||||
|
||||
@ -64,13 +65,11 @@ void Construct::set_corresponding_constructs(
|
||||
corresponding_constructs_ = constructs;
|
||||
}
|
||||
|
||||
const BasicBlock* Construct::get_entry() const { return entry_block_; }
|
||||
BasicBlock* Construct::get_entry() { return entry_block_; }
|
||||
const BasicBlock* Construct::entry_block() const { return entry_block_; }
|
||||
BasicBlock* Construct::entry_block() { return entry_block_; }
|
||||
|
||||
const BasicBlock* Construct::get_exit() const { return exit_block_; }
|
||||
BasicBlock* Construct::get_exit() { return exit_block_; }
|
||||
const BasicBlock* Construct::exit_block() const { return exit_block_; }
|
||||
BasicBlock* Construct::exit_block() { return exit_block_; }
|
||||
|
||||
void Construct::set_exit(BasicBlock* exit_block) {
|
||||
exit_block_ = exit_block;
|
||||
}
|
||||
void Construct::set_exit(BasicBlock* block) { exit_block_ = block; }
|
||||
} /// namespace libspirv
|
||||
|
@ -61,21 +61,21 @@ class Construct {
|
||||
std::vector<Construct*> constructs = {});
|
||||
|
||||
/// Returns the type of the construct
|
||||
ConstructType get_type() const;
|
||||
ConstructType type() const;
|
||||
|
||||
const std::vector<Construct*>& get_corresponding_constructs() const;
|
||||
std::vector<Construct*>& get_corresponding_constructs();
|
||||
const std::vector<Construct*>& corresponding_constructs() const;
|
||||
std::vector<Construct*>& corresponding_constructs();
|
||||
void set_corresponding_constructs(std::vector<Construct*> constructs);
|
||||
|
||||
/// Returns the dominator block of the construct.
|
||||
///
|
||||
/// This is usually the header block or the first block of the construct.
|
||||
const BasicBlock* get_entry() const;
|
||||
const BasicBlock* entry_block() const;
|
||||
|
||||
/// Returns the dominator block of the construct.
|
||||
///
|
||||
/// This is usually the header block or the first block of the construct.
|
||||
BasicBlock* get_entry();
|
||||
BasicBlock* entry_block();
|
||||
|
||||
/// Returns the exit block of the construct.
|
||||
///
|
||||
@ -83,7 +83,7 @@ class Construct {
|
||||
/// loop construct. For the case construct it is the block that branches to
|
||||
/// the OpSwitch merge block or other case blocks. Otherwise it is the merge
|
||||
/// block of the corresponding header block
|
||||
const BasicBlock* get_exit() const;
|
||||
const BasicBlock* exit_block() const;
|
||||
|
||||
/// Returns the exit block of the construct.
|
||||
///
|
||||
@ -91,7 +91,7 @@ class Construct {
|
||||
/// loop construct. For the case construct it is the block that branches to
|
||||
/// the OpSwitch merge block or other case blocks. Otherwise it is the merge
|
||||
/// block of the corresponding header block
|
||||
BasicBlock* get_exit();
|
||||
BasicBlock* exit_block();
|
||||
|
||||
/// Sets the exit block for this construct. This is useful for continue
|
||||
/// constructs which do not know the back-edge block during construction
|
||||
|
@ -48,23 +48,23 @@ namespace {
|
||||
|
||||
void printDot(const BasicBlock& other, const ValidationState_t& module) {
|
||||
string block_string;
|
||||
if (other.get_successors()->empty()) {
|
||||
if (other.successors()->empty()) {
|
||||
block_string += "end ";
|
||||
} else {
|
||||
for (auto block : *other.get_successors()) {
|
||||
block_string += module.getIdOrName(block->get_id()) + " ";
|
||||
for (auto block : *other.successors()) {
|
||||
block_string += module.getIdOrName(block->id()) + " ";
|
||||
}
|
||||
}
|
||||
printf("%10s -> {%s\b}\n", module.getIdOrName(other.get_id()).c_str(),
|
||||
printf("%10s -> {%s\b}\n", module.getIdOrName(other.id()).c_str(),
|
||||
block_string.c_str());
|
||||
}
|
||||
} /// namespace
|
||||
|
||||
Function::Function(uint32_t id, uint32_t result_type_id,
|
||||
Function::Function(uint32_t function_id, uint32_t result_type_id,
|
||||
SpvFunctionControlMask function_control,
|
||||
uint32_t function_type_id, ValidationState_t& module)
|
||||
: module_(module),
|
||||
id_(id),
|
||||
id_(function_id),
|
||||
function_type_id_(function_type_id),
|
||||
result_type_id_(result_type_id),
|
||||
function_control_(function_control),
|
||||
@ -80,11 +80,11 @@ Function::Function(uint32_t id, uint32_t result_type_id,
|
||||
variable_ids_(),
|
||||
parameter_ids_() {}
|
||||
|
||||
bool Function::IsFirstBlock(uint32_t id) const {
|
||||
return !ordered_blocks_.empty() && *get_first_block() == id;
|
||||
bool Function::IsFirstBlock(uint32_t block_id) const {
|
||||
return !ordered_blocks_.empty() && *first_block() == block_id;
|
||||
}
|
||||
|
||||
spv_result_t Function::RegisterFunctionParameter(uint32_t id,
|
||||
spv_result_t Function::RegisterFunctionParameter(uint32_t parameter_id,
|
||||
uint32_t type_id) {
|
||||
assert(module_.in_function_body() == true &&
|
||||
"RegisterFunctionParameter can only be called when parsing the binary "
|
||||
@ -94,7 +94,7 @@ spv_result_t Function::RegisterFunctionParameter(uint32_t id,
|
||||
"ouside of a block");
|
||||
// TODO(umar): Validate function parameter type order and count
|
||||
// TODO(umar): Use these variables to validate parameter type
|
||||
(void)id;
|
||||
(void)parameter_id;
|
||||
(void)type_id;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
@ -128,24 +128,24 @@ spv_result_t Function::RegisterSelectionMerge(uint32_t merge_id) {
|
||||
current_block_->set_type(kBlockTypeHeader);
|
||||
merge_block.set_type(kBlockTypeMerge);
|
||||
|
||||
cfg_constructs_.emplace_back(ConstructType::kSelection, get_current_block(),
|
||||
cfg_constructs_.emplace_back(ConstructType::kSelection, current_block(),
|
||||
&merge_block);
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
void Function::printDotGraph() const {
|
||||
if (get_first_block()) {
|
||||
void Function::PrintDotGraph() const {
|
||||
if (first_block()) {
|
||||
string func_name(module_.getIdOrName(id_));
|
||||
printf("digraph %s {\n", func_name.c_str());
|
||||
printBlocks();
|
||||
PrintBlocks();
|
||||
printf("}\n");
|
||||
}
|
||||
}
|
||||
|
||||
void Function::printBlocks() const {
|
||||
if (get_first_block()) {
|
||||
void Function::PrintBlocks() const {
|
||||
if (first_block()) {
|
||||
printf("%10s -> %s\n", module_.getIdOrName(id_).c_str(),
|
||||
module_.getIdOrName(get_first_block()->get_id()).c_str());
|
||||
module_.getIdOrName(first_block()->id()).c_str());
|
||||
for (const auto& block : blocks_) {
|
||||
printDot(block.second, module_);
|
||||
}
|
||||
@ -158,11 +158,11 @@ spv_result_t Function::RegisterSetFunctionDeclType(FunctionDecl type) {
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t Function::RegisterBlock(uint32_t id, bool is_definition) {
|
||||
spv_result_t Function::RegisterBlock(uint32_t block_id, bool is_definition) {
|
||||
assert(module_.in_function_body() == true &&
|
||||
"RegisterBlocks can only be called when parsing a binary inside of a "
|
||||
"function");
|
||||
assert(module_.getLayoutSection() !=
|
||||
assert(module_.current_layout_section() !=
|
||||
ModuleLayoutSection::kLayoutFunctionDeclarations &&
|
||||
"RegisterBlocks cannot be called within a function declaration");
|
||||
assert(
|
||||
@ -171,18 +171,19 @@ spv_result_t Function::RegisterBlock(uint32_t id, bool is_definition) {
|
||||
|
||||
std::unordered_map<uint32_t, BasicBlock>::iterator inserted_block;
|
||||
bool success = false;
|
||||
tie(inserted_block, success) = blocks_.insert({id, BasicBlock(id)});
|
||||
tie(inserted_block, success) =
|
||||
blocks_.insert({block_id, BasicBlock(block_id)});
|
||||
if (is_definition) { // new block definition
|
||||
assert(current_block_ == nullptr &&
|
||||
"Register Block can only be called when parsing a binary outside of "
|
||||
"a BasicBlock");
|
||||
|
||||
undefined_blocks_.erase(id);
|
||||
undefined_blocks_.erase(block_id);
|
||||
current_block_ = &inserted_block->second;
|
||||
ordered_blocks_.push_back(current_block_);
|
||||
if (IsFirstBlock(id)) current_block_->set_reachable(true);
|
||||
if (IsFirstBlock(block_id)) current_block_->set_reachable(true);
|
||||
} else if (success) { // Block doesn't exsist but this is not a definition
|
||||
undefined_blocks_.insert(id);
|
||||
undefined_blocks_.insert(block_id);
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
@ -202,10 +203,11 @@ void Function::RegisterBlockEnd(vector<uint32_t> next_list,
|
||||
|
||||
std::unordered_map<uint32_t, BasicBlock>::iterator inserted_block;
|
||||
bool success;
|
||||
for (uint32_t id : next_list) {
|
||||
tie(inserted_block, success) = blocks_.insert({id, BasicBlock(id)});
|
||||
for (uint32_t successor_id : next_list) {
|
||||
tie(inserted_block, success) =
|
||||
blocks_.insert({successor_id, BasicBlock(successor_id)});
|
||||
if (success) {
|
||||
undefined_blocks_.insert(id);
|
||||
undefined_blocks_.insert(successor_id);
|
||||
}
|
||||
next_blocks.push_back(&inserted_block->second);
|
||||
}
|
||||
@ -225,48 +227,46 @@ void Function::RegisterFunctionEnd() {
|
||||
vector<BasicBlock*> sources;
|
||||
vector<BasicBlock*> sinks;
|
||||
for (const auto b : ordered_blocks_) {
|
||||
if (b->get_predecessors()->empty()) sources.push_back(b);
|
||||
if (b->get_successors()->empty()) sinks.push_back(b);
|
||||
if (b->predecessors()->empty()) sources.push_back(b);
|
||||
if (b->successors()->empty()) sinks.push_back(b);
|
||||
}
|
||||
pseudo_entry_block_.SetSuccessorsUnsafe(std::move(sources));
|
||||
pseudo_exit_block_.SetPredecessorsUnsafe(std::move(sinks));
|
||||
}
|
||||
}
|
||||
|
||||
size_t Function::get_block_count() const { return blocks_.size(); }
|
||||
size_t Function::block_count() const { return blocks_.size(); }
|
||||
|
||||
size_t Function::get_undefined_block_count() const {
|
||||
size_t Function::undefined_block_count() const {
|
||||
return undefined_blocks_.size();
|
||||
}
|
||||
|
||||
const vector<BasicBlock*>& Function::get_blocks() const {
|
||||
const vector<BasicBlock*>& Function::ordered_blocks() const {
|
||||
return ordered_blocks_;
|
||||
}
|
||||
vector<BasicBlock*>& Function::get_blocks() { return ordered_blocks_; }
|
||||
vector<BasicBlock*>& Function::ordered_blocks() { return ordered_blocks_; }
|
||||
|
||||
const BasicBlock* Function::get_current_block() const { return current_block_; }
|
||||
BasicBlock* Function::get_current_block() { return current_block_; }
|
||||
const BasicBlock* Function::current_block() const { return current_block_; }
|
||||
BasicBlock* Function::current_block() { return current_block_; }
|
||||
|
||||
BasicBlock* Function::get_pseudo_entry_block() { return &pseudo_entry_block_; }
|
||||
const BasicBlock* Function::get_pseudo_entry_block() const {
|
||||
BasicBlock* Function::pseudo_entry_block() { return &pseudo_entry_block_; }
|
||||
const BasicBlock* Function::pseudo_entry_block() const {
|
||||
return &pseudo_entry_block_;
|
||||
}
|
||||
|
||||
BasicBlock* Function::get_pseudo_exit_block() { return &pseudo_exit_block_; }
|
||||
const BasicBlock* Function::get_pseudo_exit_block() const {
|
||||
BasicBlock* Function::pseudo_exit_block() { return &pseudo_exit_block_; }
|
||||
const BasicBlock* Function::pseudo_exit_block() const {
|
||||
return &pseudo_exit_block_;
|
||||
}
|
||||
|
||||
const list<Construct>& Function::get_constructs() const {
|
||||
return cfg_constructs_;
|
||||
}
|
||||
list<Construct>& Function::get_constructs() { return cfg_constructs_; }
|
||||
const list<Construct>& Function::constructs() const { return cfg_constructs_; }
|
||||
list<Construct>& Function::constructs() { return cfg_constructs_; }
|
||||
|
||||
const BasicBlock* Function::get_first_block() const {
|
||||
const BasicBlock* Function::first_block() const {
|
||||
if (ordered_blocks_.empty()) return nullptr;
|
||||
return ordered_blocks_[0];
|
||||
}
|
||||
BasicBlock* Function::get_first_block() {
|
||||
BasicBlock* Function::first_block() {
|
||||
if (ordered_blocks_.empty()) return nullptr;
|
||||
return ordered_blocks_[0];
|
||||
}
|
||||
@ -281,22 +281,22 @@ bool Function::IsBlockType(uint32_t merge_block_id, BlockType type) const {
|
||||
return ret;
|
||||
}
|
||||
|
||||
pair<const BasicBlock*, bool> Function::GetBlock(uint32_t id) const {
|
||||
const auto b = blocks_.find(id);
|
||||
pair<const BasicBlock*, bool> Function::GetBlock(uint32_t block_id) const {
|
||||
const auto b = blocks_.find(block_id);
|
||||
if (b != end(blocks_)) {
|
||||
const BasicBlock* block = &(b->second);
|
||||
bool defined =
|
||||
undefined_blocks_.find(block->get_id()) == end(undefined_blocks_);
|
||||
undefined_blocks_.find(block->id()) == end(undefined_blocks_);
|
||||
return make_pair(block, defined);
|
||||
} else {
|
||||
return make_pair(nullptr, false);
|
||||
}
|
||||
}
|
||||
|
||||
pair<BasicBlock*, bool> Function::GetBlock(uint32_t id) {
|
||||
pair<BasicBlock*, bool> Function::GetBlock(uint32_t block_id) {
|
||||
const BasicBlock* out;
|
||||
bool defined;
|
||||
tie(out, defined) = const_cast<const Function*>(this)->GetBlock(id);
|
||||
tie(out, defined) = const_cast<const Function*>(this)->GetBlock(block_id);
|
||||
return make_pair(const_cast<BasicBlock*>(out), defined);
|
||||
}
|
||||
} /// namespace libspirv
|
||||
|
@ -32,8 +32,8 @@
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "spirv/1.1/spirv.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "spirv/1.1/spirv.h"
|
||||
#include "val/BasicBlock.h"
|
||||
|
||||
namespace libspirv {
|
||||
@ -117,72 +117,72 @@ class Function {
|
||||
std::pair<BasicBlock*, bool> GetBlock(uint32_t id);
|
||||
|
||||
/// Returns the first block of the current function
|
||||
const BasicBlock* get_first_block() const;
|
||||
const BasicBlock* first_block() const;
|
||||
|
||||
/// Returns the first block of the current function
|
||||
BasicBlock* get_first_block();
|
||||
BasicBlock* first_block();
|
||||
|
||||
/// Returns a vector of all the blocks in the function
|
||||
const std::vector<BasicBlock*>& get_blocks() const;
|
||||
const std::vector<BasicBlock*>& ordered_blocks() const;
|
||||
|
||||
/// Returns a vector of all the blocks in the function
|
||||
std::vector<BasicBlock*>& get_blocks();
|
||||
std::vector<BasicBlock*>& ordered_blocks();
|
||||
|
||||
/// Returns a list of all the cfg constructs in the function
|
||||
const std::list<Construct>& get_constructs() const;
|
||||
const std::list<Construct>& constructs() const;
|
||||
|
||||
/// Returns a list of all the cfg constructs in the function
|
||||
std::list<Construct>& get_constructs();
|
||||
std::list<Construct>& constructs();
|
||||
|
||||
/// Returns the number of blocks in the current function being parsed
|
||||
size_t get_block_count() const;
|
||||
size_t block_count() const;
|
||||
|
||||
/// Returns the id of the funciton
|
||||
uint32_t get_id() const { return id_; }
|
||||
uint32_t 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 {
|
||||
size_t undefined_block_count() const;
|
||||
const std::unordered_set<uint32_t>& undefined_blocks() const {
|
||||
return undefined_blocks_;
|
||||
}
|
||||
|
||||
/// Returns the block that is currently being parsed in the binary
|
||||
BasicBlock* get_current_block();
|
||||
BasicBlock* current_block();
|
||||
|
||||
/// Returns the block that is currently being parsed in the binary
|
||||
const BasicBlock* get_current_block() const;
|
||||
const BasicBlock* current_block() const;
|
||||
|
||||
/// Returns the pseudo exit block
|
||||
BasicBlock* get_pseudo_entry_block();
|
||||
BasicBlock* pseudo_entry_block();
|
||||
|
||||
/// Returns the pseudo exit block
|
||||
const BasicBlock* get_pseudo_entry_block() const;
|
||||
const BasicBlock* pseudo_entry_block() const;
|
||||
|
||||
/// Returns the pseudo exit block
|
||||
BasicBlock* get_pseudo_exit_block();
|
||||
BasicBlock* pseudo_exit_block();
|
||||
|
||||
/// Returns the pseudo exit block
|
||||
const BasicBlock* get_pseudo_exit_block() const;
|
||||
const BasicBlock* pseudo_exit_block() const;
|
||||
|
||||
/// Returns a vector with just the pseudo entry block.
|
||||
/// This serves as the predecessors of each source node in the CFG when computing
|
||||
/// dominators.
|
||||
const std::vector<BasicBlock*>* get_pseudo_entry_blocks() const {
|
||||
/// This serves as the predecessors of each source node in the CFG when
|
||||
/// computing dominators.
|
||||
const std::vector<BasicBlock*>* pseudo_entry_blocks() const {
|
||||
return &pseudo_entry_blocks_;
|
||||
}
|
||||
|
||||
/// Returns a vector with just the pseudo exit block.
|
||||
/// This serves as the successors of each sink node in the CFG when computing
|
||||
/// dominators.
|
||||
const std::vector<BasicBlock*>* get_pseudo_exit_blocks() const {
|
||||
const std::vector<BasicBlock*>* pseudo_exit_blocks() const {
|
||||
return &pseudo_exit_blocks_;
|
||||
}
|
||||
|
||||
/// Prints a GraphViz digraph of the CFG of the current funciton
|
||||
void printDotGraph() const;
|
||||
void PrintDotGraph() const;
|
||||
|
||||
/// Prints a directed graph of the CFG of the current funciton
|
||||
void printBlocks() const;
|
||||
void PrintBlocks() const;
|
||||
|
||||
private:
|
||||
/// Parent module
|
||||
|
@ -204,17 +204,17 @@ ValidationState_t::ValidationState_t(spv_diagnostic* diagnostic,
|
||||
memory_model_(SpvMemoryModelSimple),
|
||||
in_function_(false) {}
|
||||
|
||||
spv_result_t ValidationState_t::forwardDeclareId(uint32_t id) {
|
||||
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) {
|
||||
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) {
|
||||
void ValidationState_t::AssignNameToId(uint32_t id, string name) {
|
||||
operand_names_[id] = name;
|
||||
}
|
||||
|
||||
@ -237,30 +237,30 @@ string ValidationState_t::getIdOrName(uint32_t id) const {
|
||||
return out.str();
|
||||
}
|
||||
|
||||
size_t ValidationState_t::unresolvedForwardIdCount() const {
|
||||
size_t ValidationState_t::unresolved_forward_id_count() const {
|
||||
return unresolved_forward_ids_.size();
|
||||
}
|
||||
|
||||
vector<uint32_t> ValidationState_t::unresolvedForwardIds() const {
|
||||
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 {
|
||||
bool ValidationState_t::IsDefinedId(uint32_t id) const {
|
||||
return usedefs_.FindDef(id).first;
|
||||
}
|
||||
|
||||
// Increments the instruction count. Used for diagnostic
|
||||
int ValidationState_t::incrementInstructionCount() {
|
||||
int ValidationState_t::increment_instruction_count() {
|
||||
return instruction_counter_++;
|
||||
}
|
||||
|
||||
ModuleLayoutSection ValidationState_t::getLayoutSection() const {
|
||||
ModuleLayoutSection ValidationState_t::current_layout_section() const {
|
||||
return current_layout_section_;
|
||||
}
|
||||
|
||||
void ValidationState_t::progressToNextLayoutSectionOrder() {
|
||||
void ValidationState_t::ProgressToNextLayoutSectionOrder() {
|
||||
// Guard against going past the last element(kLayoutFunctionDefinitions)
|
||||
if (current_layout_section_ <= kLayoutFunctionDefinitions) {
|
||||
current_layout_section_ =
|
||||
@ -268,7 +268,7 @@ void ValidationState_t::progressToNextLayoutSectionOrder() {
|
||||
}
|
||||
}
|
||||
|
||||
bool ValidationState_t::isOpcodeInCurrentLayoutSection(SpvOp op) {
|
||||
bool ValidationState_t::IsOpcodeInCurrentLayoutSection(SpvOp op) {
|
||||
return IsInstructionInLayoutSection(current_layout_section_, op);
|
||||
}
|
||||
|
||||
@ -278,9 +278,9 @@ DiagnosticStream ValidationState_t::diag(spv_result_t error_code) const {
|
||||
error_code);
|
||||
}
|
||||
|
||||
list<Function>& ValidationState_t::get_functions() { return module_functions_; }
|
||||
list<Function>& ValidationState_t::functions() { return module_functions_; }
|
||||
|
||||
Function& ValidationState_t::get_current_function() {
|
||||
Function& ValidationState_t::current_function() {
|
||||
assert(in_function_body());
|
||||
return module_functions_.back();
|
||||
}
|
||||
@ -289,7 +289,7 @@ bool ValidationState_t::in_function_body() const { return in_function_; }
|
||||
|
||||
bool ValidationState_t::in_block() const {
|
||||
return module_functions_.empty() == false &&
|
||||
module_functions_.back().get_current_block() != nullptr;
|
||||
module_functions_.back().current_block() != nullptr;
|
||||
}
|
||||
|
||||
void ValidationState_t::RegisterCapability(SpvCapability cap) {
|
||||
@ -301,7 +301,7 @@ void ValidationState_t::RegisterCapability(SpvCapability cap) {
|
||||
[this](SpvCapability c) { RegisterCapability(c); });
|
||||
}
|
||||
|
||||
bool ValidationState_t::hasCapability(SpvCapability cap) const {
|
||||
bool ValidationState_t::has_capability(SpvCapability cap) const {
|
||||
return (module_capabilities_ & SPV_CAPABILITY_AS_MASK(cap)) != 0;
|
||||
}
|
||||
|
||||
@ -310,24 +310,24 @@ bool ValidationState_t::HasAnyOf(spv_capability_mask_t capabilities) const {
|
||||
return true; // No capabilities requested: trivially satisfied.
|
||||
bool found = false;
|
||||
libspirv::ForEach(capabilities, [&found, this](SpvCapability c) {
|
||||
found |= hasCapability(c);
|
||||
found |= has_capability(c);
|
||||
});
|
||||
return found;
|
||||
}
|
||||
|
||||
void ValidationState_t::setAddressingModel(SpvAddressingModel am) {
|
||||
void ValidationState_t::set_addressing_model(SpvAddressingModel am) {
|
||||
addressing_model_ = am;
|
||||
}
|
||||
|
||||
SpvAddressingModel ValidationState_t::getAddressingModel() const {
|
||||
SpvAddressingModel ValidationState_t::addressing_model() const {
|
||||
return addressing_model_;
|
||||
}
|
||||
|
||||
void ValidationState_t::setMemoryModel(SpvMemoryModel mm) {
|
||||
void ValidationState_t::set_memory_model(SpvMemoryModel mm) {
|
||||
memory_model_ = mm;
|
||||
}
|
||||
|
||||
SpvMemoryModel ValidationState_t::getMemoryModel() const {
|
||||
SpvMemoryModel ValidationState_t::memory_model() const {
|
||||
return memory_model_;
|
||||
}
|
||||
|
||||
@ -353,7 +353,7 @@ spv_result_t ValidationState_t::RegisterFunctionEnd() {
|
||||
assert(in_block() == false &&
|
||||
"RegisterFunctionParameter can only be called when parsing the binary "
|
||||
"ouside of a block");
|
||||
get_current_function().RegisterFunctionEnd();
|
||||
current_function().RegisterFunctionEnd();
|
||||
in_function_ = false;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
@ -84,13 +84,13 @@ class ValidationState_t {
|
||||
const spv_const_context context);
|
||||
|
||||
/// Forward declares the id in the module
|
||||
spv_result_t forwardDeclareId(uint32_t id);
|
||||
spv_result_t ForwardDeclareId(uint32_t id);
|
||||
|
||||
/// Removes a forward declared ID if it has been defined
|
||||
spv_result_t removeIfForwardDeclared(uint32_t id);
|
||||
spv_result_t RemoveIfForwardDeclared(uint32_t id);
|
||||
|
||||
/// Assigns a name to an ID
|
||||
void assignNameToId(uint32_t id, std::string name);
|
||||
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
|
||||
@ -102,33 +102,33 @@ class ValidationState_t {
|
||||
|
||||
/// Returns the number of ID which have been forward referenced but not
|
||||
/// defined
|
||||
size_t unresolvedForwardIdCount() const;
|
||||
size_t unresolved_forward_id_count() const;
|
||||
|
||||
/// Returns a list of unresolved forward ids.
|
||||
std::vector<uint32_t> unresolvedForwardIds() const;
|
||||
std::vector<uint32_t> UnresolvedForwardIds() const;
|
||||
|
||||
/// Returns true if the id has been defined
|
||||
bool isDefinedId(uint32_t id) const;
|
||||
bool IsDefinedId(uint32_t id) const;
|
||||
|
||||
/// Increments the instruction count. Used for diagnostic
|
||||
int incrementInstructionCount();
|
||||
int increment_instruction_count();
|
||||
|
||||
/// Returns the current layout section which is being processed
|
||||
ModuleLayoutSection getLayoutSection() const;
|
||||
ModuleLayoutSection current_layout_section() const;
|
||||
|
||||
/// Increments the module_layout_order_section_
|
||||
void progressToNextLayoutSectionOrder();
|
||||
void ProgressToNextLayoutSectionOrder();
|
||||
|
||||
/// Determines if the op instruction is part of the current section
|
||||
bool isOpcodeInCurrentLayoutSection(SpvOp op);
|
||||
bool IsOpcodeInCurrentLayoutSection(SpvOp op);
|
||||
|
||||
libspirv::DiagnosticStream diag(spv_result_t error_code) const;
|
||||
|
||||
/// Returns the function states
|
||||
std::list<Function>& get_functions();
|
||||
std::list<Function>& functions();
|
||||
|
||||
/// Returns the function states
|
||||
Function& get_current_function();
|
||||
Function& current_function();
|
||||
|
||||
/// Returns true if the called after a function instruction but before the
|
||||
/// function end instruction
|
||||
@ -190,23 +190,23 @@ class ValidationState_t {
|
||||
spv_result_t RegisterFunctionEnd();
|
||||
|
||||
/// Returns true if the capability is enabled in the module.
|
||||
bool hasCapability(SpvCapability cap) const;
|
||||
bool has_capability(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);
|
||||
void set_addressing_model(SpvAddressingModel am);
|
||||
|
||||
/// Returns the addressing model of this module, or Logical if uninitialized.
|
||||
SpvAddressingModel getAddressingModel() const;
|
||||
SpvAddressingModel addressing_model() const;
|
||||
|
||||
/// Sets the memory model of this module.
|
||||
void setMemoryModel(SpvMemoryModel mm);
|
||||
void set_memory_model(SpvMemoryModel mm);
|
||||
|
||||
/// Returns the memory model of this module, or Simple if uninitialized.
|
||||
SpvMemoryModel getMemoryModel() const;
|
||||
SpvMemoryModel memory_model() const;
|
||||
|
||||
AssemblyGrammar& grammar() { return grammar_; }
|
||||
|
||||
|
@ -107,13 +107,13 @@ void DebugInstructionPass(ValidationState_t& _,
|
||||
const uint32_t target = *(inst->words + inst->operands[0].offset);
|
||||
const char* str =
|
||||
reinterpret_cast<const char*>(inst->words + inst->operands[1].offset);
|
||||
_.assignNameToId(target, str);
|
||||
_.AssignNameToId(target, str);
|
||||
} break;
|
||||
case SpvOpMemberName: {
|
||||
const uint32_t target = *(inst->words + inst->operands[0].offset);
|
||||
const char* str =
|
||||
reinterpret_cast<const char*>(inst->words + inst->operands[2].offset);
|
||||
_.assignNameToId(target, str);
|
||||
_.AssignNameToId(target, str);
|
||||
} break;
|
||||
case SpvOpSourceContinued:
|
||||
case SpvOpSource:
|
||||
@ -125,7 +125,6 @@ void DebugInstructionPass(ValidationState_t& _,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Collects use-def info about an instruction's IDs.
|
||||
@ -143,7 +142,7 @@ void ProcessIds(ValidationState_t& _, const spv_parsed_instruction_t& inst) {
|
||||
spv_result_t ProcessInstruction(void* user_data,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
ValidationState_t& _ = *(reinterpret_cast<ValidationState_t*>(user_data));
|
||||
_.incrementInstructionCount();
|
||||
_.increment_instruction_count();
|
||||
if (static_cast<SpvOp>(inst->opcode) == SpvOpEntryPoint)
|
||||
_.entry_points().push_back(inst->words[2]);
|
||||
|
||||
@ -192,9 +191,9 @@ spv_result_t spvValidate(const spv_const_context context,
|
||||
// TODO(umar): Add validation checks which require the parsing of the entire
|
||||
// module. Use the information from the ProcessInstruction pass to make the
|
||||
// checks.
|
||||
if (vstate.unresolvedForwardIdCount() > 0) {
|
||||
if (vstate.unresolved_forward_id_count() > 0) {
|
||||
stringstream ss;
|
||||
vector<uint32_t> ids = vstate.unresolvedForwardIds();
|
||||
vector<uint32_t> ids = vstate.UnresolvedForwardIds();
|
||||
|
||||
transform(begin(ids), end(ids), ostream_iterator<string>(ss, " "),
|
||||
bind(&ValidationState_t::getIdName, vstate, _1));
|
||||
|
@ -63,8 +63,8 @@ using get_blocks_func =
|
||||
/// Computes dominators using the algorithm of Cooper, Harvey, and Kennedy
|
||||
/// "A Simple, Fast Dominance Algorithm", 2001.
|
||||
///
|
||||
/// The algorithm assumes there is a unique root node (a node without predecessors),
|
||||
/// and it is therefore at the end of the postorder vector.
|
||||
/// The algorithm assumes there is a unique root node (a node without
|
||||
/// predecessors), and it is therefore at the end of the postorder vector.
|
||||
///
|
||||
/// This function calculates the dominator edges for a set of blocks in the CFG.
|
||||
/// Uses the dominator algorithm by Cooper et al.
|
||||
@ -75,9 +75,9 @@ using get_blocks_func =
|
||||
/// block
|
||||
///
|
||||
/// @return the dominator tree of the graph, as a vector of pairs of nodes.
|
||||
/// The first node in the pair is a node in the graph. The second node in the pair
|
||||
/// is its immediate dominator in the sense of Cooper et.al., where a block without
|
||||
/// predecessors (such as the root node) is its own immediate dominator.
|
||||
/// The first node in the pair is a node in the graph. The second node in the
|
||||
/// pair is its immediate dominator in the sense of Cooper et.al., where a block
|
||||
/// without predecessors (such as the root node) is its own immediate dominator.
|
||||
std::vector<std::pair<BasicBlock*, BasicBlock*>> CalculateDominators(
|
||||
const std::vector<const BasicBlock*>& postorder,
|
||||
get_blocks_func predecessor_func);
|
||||
|
@ -77,16 +77,15 @@ struct block_info {
|
||||
/// @param[in] work_list Set of blocks visited in the the depth first traversal
|
||||
/// of the CFG
|
||||
/// @param[in] id The ID of the block being checked
|
||||
/// @return true if the edge work_list.back().block->get_id() => id is a
|
||||
/// back-edge
|
||||
///
|
||||
/// @return true if the edge work_list.back().block->id() => id is a back-edge
|
||||
bool FindInWorkList(const vector<block_info>& work_list, uint32_t id) {
|
||||
for (const auto b : work_list) {
|
||||
if (b.block->get_id() == id) return true;
|
||||
if (b.block->id() == id) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// @brief Depth first traversal starting from the \p entry BasicBlock
|
||||
///
|
||||
/// This function performs a depth first traversal from the \p entry
|
||||
@ -104,7 +103,8 @@ bool FindInWorkList(const vector<block_info>& work_list, uint32_t id) {
|
||||
/// @param[in] backedge A function that will be called when a backedge is
|
||||
/// encountered during a traversal
|
||||
/// NOTE: The @p successor_func and predecessor_func each return a pointer to a
|
||||
/// collection such that iterators to that collection remain valid for the lifetime
|
||||
/// collection such that iterators to that collection remain valid for the
|
||||
/// lifetime
|
||||
/// of the algorithm
|
||||
void DepthFirstTraversal(const BasicBlock* entry,
|
||||
get_blocks_func successor_func,
|
||||
@ -120,7 +120,7 @@ void DepthFirstTraversal(const BasicBlock* entry,
|
||||
|
||||
work_list.push_back({entry, begin(*successor_func(entry))});
|
||||
preorder(entry);
|
||||
processed.insert(entry->get_id());
|
||||
processed.insert(entry->id());
|
||||
|
||||
while (!work_list.empty()) {
|
||||
block_info& top = work_list.back();
|
||||
@ -130,14 +130,14 @@ void DepthFirstTraversal(const BasicBlock* entry,
|
||||
} else {
|
||||
BasicBlock* child = *top.iter;
|
||||
top.iter++;
|
||||
if (FindInWorkList(work_list, child->get_id())) {
|
||||
if (FindInWorkList(work_list, child->id())) {
|
||||
backedge(top.block, child);
|
||||
}
|
||||
if (processed.count(child->get_id()) == 0) {
|
||||
if (processed.count(child->id()) == 0) {
|
||||
preorder(child);
|
||||
work_list.emplace_back(
|
||||
block_info{child, begin(*successor_func(child))});
|
||||
processed.insert(child->get_id());
|
||||
processed.insert(child->id());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -145,7 +145,6 @@ void DepthFirstTraversal(const BasicBlock* entry,
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
vector<pair<BasicBlock*, BasicBlock*>> CalculateDominators(
|
||||
const vector<cbb_ptr>& postorder, get_blocks_func predecessor_func) {
|
||||
struct block_detail {
|
||||
@ -209,11 +208,11 @@ vector<pair<BasicBlock*, BasicBlock*>> CalculateDominators(
|
||||
}
|
||||
|
||||
void printDominatorList(const BasicBlock& b) {
|
||||
std::cout << b.get_id() << " is dominated by: ";
|
||||
std::cout << b.id() << " is dominated by: ";
|
||||
const BasicBlock* bb = &b;
|
||||
while (bb->GetImmediateDominator() != bb) {
|
||||
bb = bb->GetImmediateDominator();
|
||||
std::cout << bb->get_id() << " ";
|
||||
while (bb->immediate_dominator() != bb) {
|
||||
bb = bb->immediate_dominator();
|
||||
std::cout << bb->id() << " ";
|
||||
}
|
||||
}
|
||||
|
||||
@ -221,19 +220,17 @@ void printDominatorList(const BasicBlock& b) {
|
||||
if (spv_result_t rcode = ASSERT_FUNC(_, TARGET)) return rcode
|
||||
|
||||
spv_result_t FirstBlockAssert(ValidationState_t& _, uint32_t target) {
|
||||
if (_.get_current_function().IsFirstBlock(target)) {
|
||||
if (_.current_function().IsFirstBlock(target)) {
|
||||
return _.diag(SPV_ERROR_INVALID_CFG)
|
||||
<< "First block " << _.getIdName(target) << " of funciton "
|
||||
<< _.getIdName(_.get_current_function().get_id())
|
||||
<< " is targeted by block "
|
||||
<< _.getIdName(
|
||||
_.get_current_function().get_current_block()->get_id());
|
||||
<< _.getIdName(_.current_function().id()) << " is targeted by block "
|
||||
<< _.getIdName(_.current_function().current_block()->id());
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t MergeBlockAssert(ValidationState_t& _, uint32_t merge_block) {
|
||||
if (_.get_current_function().IsBlockType(merge_block, kBlockTypeMerge)) {
|
||||
if (_.current_function().IsBlockType(merge_block, kBlockTypeMerge)) {
|
||||
return _.diag(SPV_ERROR_INVALID_CFG)
|
||||
<< "Block " << _.getIdName(merge_block)
|
||||
<< " is already a merge block for another header";
|
||||
@ -245,7 +242,7 @@ spv_result_t MergeBlockAssert(ValidationState_t& _, uint32_t merge_block) {
|
||||
/// identified in the CFG.
|
||||
void UpdateContinueConstructExitBlocks(
|
||||
Function& function, const vector<pair<uint32_t, uint32_t>>& back_edges) {
|
||||
auto& constructs = function.get_constructs();
|
||||
auto& constructs = function.constructs();
|
||||
// TODO(umar): Think of a faster way to do this
|
||||
for (auto& edge : back_edges) {
|
||||
uint32_t back_edge_block_id;
|
||||
@ -253,15 +250,15 @@ void UpdateContinueConstructExitBlocks(
|
||||
tie(back_edge_block_id, loop_header_block_id) = edge;
|
||||
|
||||
auto is_this_header = [=](Construct& c) {
|
||||
return c.get_type() == ConstructType::kLoop &&
|
||||
c.get_entry()->get_id() == loop_header_block_id;
|
||||
return c.type() == ConstructType::kLoop &&
|
||||
c.entry_block()->id() == loop_header_block_id;
|
||||
};
|
||||
|
||||
for (auto construct : constructs) {
|
||||
if (is_this_header(construct)) {
|
||||
Construct* continue_construct =
|
||||
construct.get_corresponding_constructs().back();
|
||||
assert(continue_construct->get_type() == ConstructType::kContinue);
|
||||
construct.corresponding_constructs().back();
|
||||
assert(continue_construct->type() == ConstructType::kContinue);
|
||||
|
||||
BasicBlock* back_edge_block;
|
||||
tie(back_edge_block, ignore) = function.GetBlock(back_edge_block_id);
|
||||
@ -286,7 +283,7 @@ string ConstructErrorString(const Construct& construct,
|
||||
dominate_text = "does not dominate";
|
||||
}
|
||||
|
||||
switch (construct.get_type()) {
|
||||
switch (construct.type()) {
|
||||
case ConstructType::kSelection:
|
||||
construct_name = "selection";
|
||||
header_name = "selection header";
|
||||
@ -344,24 +341,24 @@ spv_result_t StructuredControlFlowChecks(
|
||||
}
|
||||
|
||||
// Check construct rules
|
||||
for (const Construct& construct : function.get_constructs()) {
|
||||
auto header = construct.get_entry();
|
||||
auto merge = construct.get_exit();
|
||||
for (const Construct& construct : function.constructs()) {
|
||||
auto header = construct.entry_block();
|
||||
auto merge = construct.exit_block();
|
||||
|
||||
// if the merge block is reachable then it's dominated by the header
|
||||
if (merge->is_reachable() &&
|
||||
if (merge->reachable() &&
|
||||
find(merge->dom_begin(), merge->dom_end(), header) ==
|
||||
merge->dom_end()) {
|
||||
return _.diag(SPV_ERROR_INVALID_CFG)
|
||||
<< ConstructErrorString(construct, _.getIdName(header->get_id()),
|
||||
_.getIdName(merge->get_id()));
|
||||
<< ConstructErrorString(construct, _.getIdName(header->id()),
|
||||
_.getIdName(merge->id()));
|
||||
}
|
||||
if (construct.get_type() == ConstructType::kContinue) {
|
||||
if (construct.type() == ConstructType::kContinue) {
|
||||
if (find(header->pdom_begin(), header->pdom_end(), merge) ==
|
||||
merge->pdom_end()) {
|
||||
return _.diag(SPV_ERROR_INVALID_CFG)
|
||||
<< ConstructErrorString(construct, _.getIdName(header->get_id()),
|
||||
_.getIdName(merge->get_id()), true);
|
||||
<< ConstructErrorString(construct, _.getIdName(header->id()),
|
||||
_.getIdName(merge->id()), true);
|
||||
}
|
||||
}
|
||||
// TODO(umar): an OpSwitch block dominates all its defined case
|
||||
@ -379,17 +376,17 @@ spv_result_t StructuredControlFlowChecks(
|
||||
}
|
||||
|
||||
spv_result_t PerformCfgChecks(ValidationState_t& _) {
|
||||
for (auto& function : _.get_functions()) {
|
||||
for (auto& function : _.functions()) {
|
||||
// Check all referenced blocks are defined within a function
|
||||
if (function.get_undefined_block_count() != 0) {
|
||||
if (function.undefined_block_count() != 0) {
|
||||
string undef_blocks("{");
|
||||
for (auto undefined_block : function.get_undefined_blocks()) {
|
||||
for (auto undefined_block : function.undefined_blocks()) {
|
||||
undef_blocks += _.getIdName(undefined_block) + " ";
|
||||
}
|
||||
return _.diag(SPV_ERROR_INVALID_CFG)
|
||||
<< "Block(s) " << undef_blocks << "\b}"
|
||||
<< " are referenced but not defined in function "
|
||||
<< _.getIdName(function.get_id());
|
||||
<< _.getIdName(function.id());
|
||||
}
|
||||
|
||||
// Prepare for dominance calculations. We want to analyze all the
|
||||
@ -405,26 +402,26 @@ spv_result_t PerformCfgChecks(ValidationState_t& _) {
|
||||
// from the pseudo entry node, and not reachable by following
|
||||
// predecessors from the pseudo exit node.
|
||||
|
||||
auto* pseudo_entry = function.get_pseudo_entry_block();
|
||||
auto* pseudo_exit = function.get_pseudo_exit_block();
|
||||
auto* pseudo_entry = function.pseudo_entry_block();
|
||||
auto* pseudo_exit = function.pseudo_exit_block();
|
||||
// We need vectors to use as the predecessors (in the augmented CFG)
|
||||
// for the source nodes of the original CFG. It must have a stable
|
||||
// address for the duration of the calculation.
|
||||
auto* pseudo_entry_vec = function.get_pseudo_entry_blocks();
|
||||
auto* pseudo_entry_vec = function.pseudo_entry_blocks();
|
||||
// Similarly, we need a vector to be used as the successors (in the
|
||||
// augmented CFG) for sinks in the original CFG.
|
||||
auto* pseudo_exit_vec = function.get_pseudo_exit_blocks();
|
||||
auto* pseudo_exit_vec = function.pseudo_exit_blocks();
|
||||
// Returns the predecessors of a block in the augmented CFG.
|
||||
auto augmented_predecessor_fn = [pseudo_entry, pseudo_entry_vec](
|
||||
const BasicBlock* block) {
|
||||
auto predecessors = block->get_predecessors();
|
||||
auto predecessors = block->predecessors();
|
||||
return (block != pseudo_entry && predecessors->empty()) ? pseudo_entry_vec
|
||||
: predecessors;
|
||||
};
|
||||
// Returns the successors of a block in the augmented CFG.
|
||||
auto augmented_successor_fn = [pseudo_exit,
|
||||
pseudo_exit_vec](const BasicBlock* block) {
|
||||
auto successors = block->get_successors();
|
||||
auto successors = block->successors();
|
||||
return (block != pseudo_exit && successors->empty()) ? pseudo_exit_vec
|
||||
: successors;
|
||||
};
|
||||
@ -434,13 +431,12 @@ spv_result_t PerformCfgChecks(ValidationState_t& _) {
|
||||
vector<const BasicBlock*> postorder;
|
||||
vector<const BasicBlock*> postdom_postorder;
|
||||
vector<pair<uint32_t, uint32_t>> back_edges;
|
||||
if (!function.get_blocks().empty()) {
|
||||
if (!function.ordered_blocks().empty()) {
|
||||
/// calculate dominators
|
||||
DepthFirstTraversal(pseudo_entry, augmented_successor_fn, [](cbb_ptr) {},
|
||||
[&](cbb_ptr b) { postorder.push_back(b); },
|
||||
[&](cbb_ptr from, cbb_ptr to) {
|
||||
back_edges.emplace_back(from->get_id(),
|
||||
to->get_id());
|
||||
back_edges.emplace_back(from->id(), to->id());
|
||||
});
|
||||
auto edges =
|
||||
libspirv::CalculateDominators(postorder, augmented_predecessor_fn);
|
||||
@ -462,23 +458,23 @@ spv_result_t PerformCfgChecks(ValidationState_t& _) {
|
||||
|
||||
// Check if the order of blocks in the binary appear before the blocks they
|
||||
// dominate
|
||||
auto& blocks = function.get_blocks();
|
||||
auto& blocks = function.ordered_blocks();
|
||||
if (blocks.empty() == false) {
|
||||
for (auto block = begin(blocks) + 1; block != end(blocks); ++block) {
|
||||
if (auto idom = (*block)->GetImmediateDominator()) {
|
||||
if (auto idom = (*block)->immediate_dominator()) {
|
||||
if (idom != pseudo_entry &&
|
||||
block == std::find(begin(blocks), block, idom)) {
|
||||
return _.diag(SPV_ERROR_INVALID_CFG)
|
||||
<< "Block " << _.getIdName((*block)->get_id())
|
||||
<< "Block " << _.getIdName((*block)->id())
|
||||
<< " appears in the binary before its dominator "
|
||||
<< _.getIdName(idom->get_id());
|
||||
<< _.getIdName(idom->id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Structured control flow checks are only required for shader capabilities
|
||||
if (_.hasCapability(SpvCapabilityShader)) {
|
||||
if (_.has_capability(SpvCapabilityShader)) {
|
||||
spvCheckReturn(StructuredControlFlowChecks(_, function, back_edges));
|
||||
}
|
||||
}
|
||||
@ -490,28 +486,27 @@ spv_result_t CfgPass(ValidationState_t& _,
|
||||
SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
switch (opcode) {
|
||||
case SpvOpLabel:
|
||||
spvCheckReturn(_.get_current_function().RegisterBlock(inst->result_id));
|
||||
spvCheckReturn(_.current_function().RegisterBlock(inst->result_id));
|
||||
break;
|
||||
case SpvOpLoopMerge: {
|
||||
uint32_t merge_block = inst->words[inst->operands[0].offset];
|
||||
uint32_t continue_block = inst->words[inst->operands[1].offset];
|
||||
CFG_ASSERT(MergeBlockAssert, merge_block);
|
||||
|
||||
spvCheckReturn(_.get_current_function().RegisterLoopMerge(
|
||||
merge_block, continue_block));
|
||||
spvCheckReturn(
|
||||
_.current_function().RegisterLoopMerge(merge_block, continue_block));
|
||||
} break;
|
||||
case SpvOpSelectionMerge: {
|
||||
uint32_t merge_block = inst->words[inst->operands[0].offset];
|
||||
CFG_ASSERT(MergeBlockAssert, merge_block);
|
||||
|
||||
spvCheckReturn(
|
||||
_.get_current_function().RegisterSelectionMerge(merge_block));
|
||||
spvCheckReturn(_.current_function().RegisterSelectionMerge(merge_block));
|
||||
} break;
|
||||
case SpvOpBranch: {
|
||||
uint32_t target = inst->words[inst->operands[0].offset];
|
||||
CFG_ASSERT(FirstBlockAssert, target);
|
||||
|
||||
_.get_current_function().RegisterBlockEnd({target}, opcode);
|
||||
_.current_function().RegisterBlockEnd({target}, opcode);
|
||||
} break;
|
||||
case SpvOpBranchConditional: {
|
||||
uint32_t tlabel = inst->words[inst->operands[1].offset];
|
||||
@ -519,7 +514,7 @@ spv_result_t CfgPass(ValidationState_t& _,
|
||||
CFG_ASSERT(FirstBlockAssert, tlabel);
|
||||
CFG_ASSERT(FirstBlockAssert, flabel);
|
||||
|
||||
_.get_current_function().RegisterBlockEnd({tlabel, flabel}, opcode);
|
||||
_.current_function().RegisterBlockEnd({tlabel, flabel}, opcode);
|
||||
} break;
|
||||
|
||||
case SpvOpSwitch: {
|
||||
@ -529,13 +524,13 @@ spv_result_t CfgPass(ValidationState_t& _,
|
||||
CFG_ASSERT(FirstBlockAssert, target);
|
||||
cases.push_back(target);
|
||||
}
|
||||
_.get_current_function().RegisterBlockEnd({cases}, opcode);
|
||||
_.current_function().RegisterBlockEnd({cases}, opcode);
|
||||
} break;
|
||||
case SpvOpKill:
|
||||
case SpvOpReturn:
|
||||
case SpvOpReturnValue:
|
||||
case SpvOpUnreachable:
|
||||
_.get_current_function().RegisterBlockEnd({}, opcode);
|
||||
_.current_function().RegisterBlockEnd({}, opcode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -2349,7 +2349,7 @@ spv_result_t spvValidateInstructionIDs(const spv_instruction_t* pInsts,
|
||||
spv_position position,
|
||||
spv_diagnostic* pDiag) {
|
||||
idUsage idUsage(opcodeTable, operandTable, extInstTable, pInsts, instCount,
|
||||
state.getMemoryModel(), state.getAddressingModel(),
|
||||
state.memory_model(), state.addressing_model(),
|
||||
state.usedefs(), state.entry_points(), position, pDiag);
|
||||
for (uint64_t instIndex = 0; instIndex < instCount; ++instIndex) {
|
||||
spvCheck(!idUsage.isValid(&pInsts[instIndex]), return SPV_ERROR_INVALID_ID);
|
||||
|
@ -80,7 +80,7 @@ spv_capability_mask_t RequiredCapabilities(const AssemblyGrammar& grammar,
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace anonymous
|
||||
} // namespace
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
@ -127,9 +127,9 @@ spv_result_t InstructionPass(ValidationState_t& _,
|
||||
_.RegisterCapability(
|
||||
static_cast<SpvCapability>(inst->words[inst->operands[0].offset]));
|
||||
if (opcode == SpvOpMemoryModel) {
|
||||
_.setAddressingModel(
|
||||
_.set_addressing_model(
|
||||
static_cast<SpvAddressingModel>(inst->words[inst->operands[0].offset]));
|
||||
_.setMemoryModel(
|
||||
_.set_memory_model(
|
||||
static_cast<SpvMemoryModel>(inst->words[inst->operands[1].offset]));
|
||||
}
|
||||
if (opcode == SpvOpVariable) {
|
||||
@ -138,15 +138,17 @@ spv_result_t InstructionPass(ValidationState_t& _,
|
||||
if (storage_class == SpvStorageClassGeneric)
|
||||
return _.diag(SPV_ERROR_INVALID_BINARY)
|
||||
<< "OpVariable storage class cannot be Generic";
|
||||
if (_.getLayoutSection() == kLayoutFunctionDefinitions) {
|
||||
if (_.current_layout_section() == kLayoutFunctionDefinitions) {
|
||||
if (storage_class != SpvStorageClassFunction) {
|
||||
return _.diag(SPV_ERROR_INVALID_LAYOUT)
|
||||
<< "Variables must have a function[7] storage class inside"
|
||||
" of a function";
|
||||
}
|
||||
if(_.get_current_function().IsFirstBlock(_.get_current_function().get_current_block()->get_id()) == false) {
|
||||
return _.diag(SPV_ERROR_INVALID_CFG)
|
||||
<< "Variables can only be defined in the first block of a function";
|
||||
if (_.current_function().IsFirstBlock(
|
||||
_.current_function().current_block()->id()) == false) {
|
||||
return _.diag(SPV_ERROR_INVALID_CFG) << "Variables can only be defined "
|
||||
"in the first block of a "
|
||||
"function";
|
||||
}
|
||||
} else {
|
||||
if (storage_class == SpvStorageClassFunction) {
|
||||
|
@ -50,10 +50,10 @@ namespace {
|
||||
spv_result_t ModuleScopedInstructions(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst,
|
||||
SpvOp opcode) {
|
||||
while (_.isOpcodeInCurrentLayoutSection(opcode) == false) {
|
||||
_.progressToNextLayoutSectionOrder();
|
||||
while (_.IsOpcodeInCurrentLayoutSection(opcode) == false) {
|
||||
_.ProgressToNextLayoutSectionOrder();
|
||||
|
||||
switch (_.getLayoutSection()) {
|
||||
switch (_.current_layout_section()) {
|
||||
case kLayoutMemoryModel:
|
||||
if (opcode != SpvOpMemoryModel) {
|
||||
return _.diag(SPV_ERROR_INVALID_LAYOUT)
|
||||
@ -80,7 +80,7 @@ spv_result_t ModuleScopedInstructions(ValidationState_t& _,
|
||||
spv_result_t FunctionScopedInstructions(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst,
|
||||
SpvOp opcode) {
|
||||
if (_.isOpcodeInCurrentLayoutSection(opcode)) {
|
||||
if (_.IsOpcodeInCurrentLayoutSection(opcode)) {
|
||||
switch (opcode) {
|
||||
case SpvOpFunction: {
|
||||
if (_.in_function_body()) {
|
||||
@ -92,8 +92,8 @@ spv_result_t FunctionScopedInstructions(ValidationState_t& _,
|
||||
spvCheckReturn(
|
||||
_.RegisterFunction(inst->result_id, inst->type_id, control_mask,
|
||||
inst->words[inst->operands[3].offset]));
|
||||
if (_.getLayoutSection() == kLayoutFunctionDefinitions)
|
||||
spvCheckReturn(_.get_current_function().RegisterSetFunctionDeclType(
|
||||
if (_.current_layout_section() == kLayoutFunctionDefinitions)
|
||||
spvCheckReturn(_.current_function().RegisterSetFunctionDeclType(
|
||||
FunctionDecl::kFunctionDeclDefinition));
|
||||
} break;
|
||||
|
||||
@ -103,13 +103,12 @@ spv_result_t FunctionScopedInstructions(ValidationState_t& _,
|
||||
"instructions must be in "
|
||||
"a function body";
|
||||
}
|
||||
if (_.get_current_function().get_block_count() != 0) {
|
||||
if (_.current_function().block_count() != 0) {
|
||||
return _.diag(SPV_ERROR_INVALID_LAYOUT)
|
||||
<< "Function parameters must only appear immediately after "
|
||||
"the "
|
||||
"function definition";
|
||||
"the function definition";
|
||||
}
|
||||
spvCheckReturn(_.get_current_function().RegisterFunctionParameter(
|
||||
spvCheckReturn(_.current_function().RegisterFunctionParameter(
|
||||
inst->result_id, inst->type_id));
|
||||
break;
|
||||
|
||||
@ -122,14 +121,14 @@ spv_result_t FunctionScopedInstructions(ValidationState_t& _,
|
||||
return _.diag(SPV_ERROR_INVALID_LAYOUT)
|
||||
<< "Function end cannot be called in blocks";
|
||||
}
|
||||
if (_.get_current_function().get_block_count() == 0 &&
|
||||
_.getLayoutSection() == kLayoutFunctionDefinitions) {
|
||||
if (_.current_function().block_count() == 0 &&
|
||||
_.current_layout_section() == kLayoutFunctionDefinitions) {
|
||||
return _.diag(SPV_ERROR_INVALID_LAYOUT) << "Function declarations "
|
||||
"must appear before "
|
||||
"function definitions.";
|
||||
}
|
||||
if (_.getLayoutSection() == kLayoutFunctionDeclarations) {
|
||||
spvCheckReturn(_.get_current_function().RegisterSetFunctionDeclType(
|
||||
if (_.current_layout_section() == kLayoutFunctionDeclarations) {
|
||||
spvCheckReturn(_.current_function().RegisterSetFunctionDeclType(
|
||||
FunctionDecl::kFunctionDeclDeclaration));
|
||||
}
|
||||
spvCheckReturn(_.RegisterFunctionEnd());
|
||||
@ -150,15 +149,15 @@ spv_result_t FunctionScopedInstructions(ValidationState_t& _,
|
||||
return _.diag(SPV_ERROR_INVALID_LAYOUT)
|
||||
<< "A block must end with a branch instruction.";
|
||||
}
|
||||
if (_.getLayoutSection() == kLayoutFunctionDeclarations) {
|
||||
_.progressToNextLayoutSectionOrder();
|
||||
spvCheckReturn(_.get_current_function().RegisterSetFunctionDeclType(
|
||||
if (_.current_layout_section() == kLayoutFunctionDeclarations) {
|
||||
_.ProgressToNextLayoutSectionOrder();
|
||||
spvCheckReturn(_.current_function().RegisterSetFunctionDeclType(
|
||||
FunctionDecl::kFunctionDeclDefinition));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (_.getLayoutSection() == kLayoutFunctionDeclarations &&
|
||||
if (_.current_layout_section() == kLayoutFunctionDeclarations &&
|
||||
_.in_function_body()) {
|
||||
return _.diag(SPV_ERROR_INVALID_LAYOUT)
|
||||
<< "A function must begin with a label";
|
||||
@ -188,7 +187,7 @@ spv_result_t ModuleLayoutPass(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
|
||||
switch (_.getLayoutSection()) {
|
||||
switch (_.current_layout_section()) {
|
||||
case kLayoutCapabilities:
|
||||
case kLayoutExtensions:
|
||||
case kLayoutExtInstImport:
|
||||
|
@ -88,7 +88,7 @@ function<bool(unsigned)> getCanBeForwardDeclaredFunction(SpvOp opcode) {
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
@ -112,17 +112,17 @@ spv_result_t SsaPass(ValidationState_t& _,
|
||||
auto ret = SPV_ERROR_INTERNAL;
|
||||
switch (type) {
|
||||
case SPV_OPERAND_TYPE_RESULT_ID:
|
||||
_.removeIfForwardDeclared(*operand_ptr);
|
||||
_.RemoveIfForwardDeclared(*operand_ptr);
|
||||
ret = SPV_SUCCESS;
|
||||
break;
|
||||
case SPV_OPERAND_TYPE_ID:
|
||||
case SPV_OPERAND_TYPE_TYPE_ID:
|
||||
case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
|
||||
case SPV_OPERAND_TYPE_SCOPE_ID:
|
||||
if (_.isDefinedId(*operand_ptr)) {
|
||||
if (_.IsDefinedId(*operand_ptr)) {
|
||||
ret = SPV_SUCCESS;
|
||||
} else if (can_have_forward_declared_ids(i)) {
|
||||
ret = _.forwardDeclareId(*operand_ptr);
|
||||
ret = _.ForwardDeclareId(*operand_ptr);
|
||||
} else {
|
||||
ret = _.diag(SPV_ERROR_INVALID_ID) << "ID "
|
||||
<< _.getIdName(*operand_ptr)
|
||||
@ -139,4 +139,4 @@ spv_result_t SsaPass(ValidationState_t& _,
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
}
|
||||
} // namespace libspirv
|
||||
|
Loading…
Reference in New Issue
Block a user