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