Updated spirv-tools.
This commit is contained in:
parent
15a4bcda82
commit
274757090d
27
3rdparty/spirv-tools/BUILD.gn
vendored
27
3rdparty/spirv-tools/BUILD.gn
vendored
@ -295,6 +295,14 @@ config("spvtools_internal_config") {
|
||||
}
|
||||
}
|
||||
|
||||
source_set("spv_headers") {
|
||||
sources = [
|
||||
"$spirv_headers/include/spirv/1.2/GLSL.std.450.h",
|
||||
"$spirv_headers/include/spirv/unified1/OpenCL.std.h",
|
||||
"$spirv_headers/include/spirv/unified1/spirv.h",
|
||||
]
|
||||
}
|
||||
|
||||
source_set("spvtools_headers") {
|
||||
sources = [
|
||||
"include/spirv-tools/instrument.hpp",
|
||||
@ -324,16 +332,22 @@ static_library("spvtools") {
|
||||
"source/assembly_grammar.h",
|
||||
"source/binary.cpp",
|
||||
"source/binary.h",
|
||||
"source/cfa.h",
|
||||
"source/diagnostic.cpp",
|
||||
"source/diagnostic.h",
|
||||
"source/disassemble.cpp",
|
||||
"source/disassemble.h",
|
||||
"source/enum_set.h",
|
||||
"source/enum_string_mapping.cpp",
|
||||
"source/enum_string_mapping.h",
|
||||
"source/ext_inst.cpp",
|
||||
"source/ext_inst.h",
|
||||
"source/extensions.cpp",
|
||||
"source/extensions.h",
|
||||
"source/instruction.h",
|
||||
"source/latest_version_glsl_std_450_header.h",
|
||||
"source/latest_version_opencl_std_header.h",
|
||||
"source/latest_version_spirv_header.h",
|
||||
"source/libspirv.cpp",
|
||||
"source/macro.h",
|
||||
"source/name_mapper.cpp",
|
||||
@ -379,6 +393,7 @@ static_library("spvtools") {
|
||||
]
|
||||
|
||||
public_deps = [
|
||||
":spv_headers",
|
||||
":spvtools_core_enums_unified1",
|
||||
":spvtools_headers",
|
||||
]
|
||||
@ -393,8 +408,12 @@ static_library("spvtools") {
|
||||
static_library("spvtools_val") {
|
||||
sources = [
|
||||
"source/val/basic_block.cpp",
|
||||
"source/val/basic_block.h",
|
||||
"source/val/construct.cpp",
|
||||
"source/val/construct.h",
|
||||
"source/val/decoration.h",
|
||||
"source/val/function.cpp",
|
||||
"source/val/function.h",
|
||||
"source/val/instruction.cpp",
|
||||
"source/val/validate.cpp",
|
||||
"source/val/validate.h",
|
||||
@ -425,14 +444,17 @@ static_library("spvtools_val") {
|
||||
"source/val/validate_logicals.cpp",
|
||||
"source/val/validate_memory.cpp",
|
||||
"source/val/validate_memory_semantics.cpp",
|
||||
"source/val/validate_memory_semantics.h",
|
||||
"source/val/validate_misc.cpp",
|
||||
"source/val/validate_mode_setting.cpp",
|
||||
"source/val/validate_non_uniform.cpp",
|
||||
"source/val/validate_primitives.cpp",
|
||||
"source/val/validate_scopes.cpp",
|
||||
"source/val/validate_scopes.h",
|
||||
"source/val/validate_small_type_uses.cpp",
|
||||
"source/val/validate_type.cpp",
|
||||
"source/val/validation_state.cpp",
|
||||
"source/val/validation_state.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
@ -720,6 +742,7 @@ static_library("spvtools_reduce") {
|
||||
"source/reduce/reducer.h",
|
||||
"source/reduce/reduction_opportunity.cpp",
|
||||
"source/reduce/reduction_opportunity.h",
|
||||
"source/reduce/reduction_opportunity_finder.h",
|
||||
"source/reduce/reduction_pass.cpp",
|
||||
"source/reduce/reduction_pass.h",
|
||||
"source/reduce/reduction_util.cpp",
|
||||
@ -872,7 +895,9 @@ source_set("spvtools_util_cli_consumer") {
|
||||
"tools/util/cli_consumer.cpp",
|
||||
"tools/util/cli_consumer.h",
|
||||
]
|
||||
deps = [ ":spvtools_headers" ]
|
||||
deps = [
|
||||
":spvtools_headers",
|
||||
]
|
||||
configs += [ ":spvtools_internal_config" ]
|
||||
}
|
||||
|
||||
|
@ -1 +1 @@
|
||||
"v2019.5-dev", "SPIRV-Tools v2019.5-dev v2019.4-144-g42f88523"
|
||||
"v2019.5-dev", "SPIRV-Tools v2019.5-dev v2019.4-153-ge0d5544c"
|
||||
|
@ -20,14 +20,12 @@ namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
protobufs::DataDescriptor MakeDataDescriptor(uint32_t object,
|
||||
std::vector<uint32_t>&& indices,
|
||||
uint32_t num_contiguous_elements) {
|
||||
std::vector<uint32_t>&& indices) {
|
||||
protobufs::DataDescriptor result;
|
||||
result.set_object(object);
|
||||
for (auto index : indices) {
|
||||
result.add_index(index);
|
||||
}
|
||||
result.set_num_contiguous_elements(num_contiguous_elements);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -50,5 +48,22 @@ bool DataDescriptorEquals::operator()(
|
||||
second->index().begin());
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out,
|
||||
const protobufs::DataDescriptor& data_descriptor) {
|
||||
out << data_descriptor.object();
|
||||
out << "[";
|
||||
bool first = true;
|
||||
for (auto index : data_descriptor.index()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
out << ", ";
|
||||
}
|
||||
out << index;
|
||||
}
|
||||
out << "]";
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
|
||||
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
namespace spvtools {
|
||||
@ -25,8 +26,7 @@ namespace fuzz {
|
||||
// Factory method to create a data descriptor message from an object id and a
|
||||
// list of indices.
|
||||
protobufs::DataDescriptor MakeDataDescriptor(uint32_t object,
|
||||
std::vector<uint32_t>&& indices,
|
||||
uint32_t num_contiguous_elements);
|
||||
std::vector<uint32_t>&& indices);
|
||||
|
||||
// Hash function for data descriptors.
|
||||
struct DataDescriptorHash {
|
||||
@ -39,6 +39,9 @@ struct DataDescriptorEquals {
|
||||
const protobufs::DataDescriptor* second) const;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out,
|
||||
const protobufs::DataDescriptor& data_descriptor);
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
||||
|
@ -68,8 +68,6 @@ namespace fuzz {
|
||||
template <typename T, typename PointerHashT, typename PointerEqualsT>
|
||||
class EquivalenceRelation {
|
||||
public:
|
||||
using ValueSet = std::unordered_set<const T*, PointerHashT, PointerEqualsT>;
|
||||
|
||||
// Merges the equivalence classes associated with |value1| and |value2|.
|
||||
// If any of these values was not previously in the equivalence relation, it
|
||||
// is added to the pool of values known to be in the relation.
|
||||
@ -86,6 +84,7 @@ class EquivalenceRelation {
|
||||
|
||||
// Initially say that the value is its own parent and that it has no
|
||||
// children.
|
||||
assert(pointer_to_value && "Representatives should never be null.");
|
||||
parent_[pointer_to_value] = pointer_to_value;
|
||||
children_[pointer_to_value] = std::unordered_set<const T*>();
|
||||
}
|
||||
@ -105,18 +104,31 @@ class EquivalenceRelation {
|
||||
// are not already in the same class, make one the parent of the other.
|
||||
const T* representative1 = Find(value1_ptr);
|
||||
const T* representative2 = Find(value2_ptr);
|
||||
assert(representative1 && "Representatives should never be null.");
|
||||
assert(representative2 && "Representatives should never be null.");
|
||||
if (representative1 != representative2) {
|
||||
parent_[representative1] = representative2;
|
||||
children_[representative2].insert(representative1);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns exactly one representative per equivalence class.
|
||||
std::vector<const T*> GetEquivalenceClassRepresentatives() const {
|
||||
std::vector<const T*> result;
|
||||
for (auto& value : owned_values_) {
|
||||
if (parent_[value.get()] == value.get()) {
|
||||
result.push_back(value.get());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns pointers to all values in the equivalence class of |value|, which
|
||||
// must already be part of the equivalence relation.
|
||||
ValueSet GetEquivalenceClass(const T& value) const {
|
||||
std::vector<const T*> GetEquivalenceClass(const T& value) const {
|
||||
assert(Exists(value));
|
||||
|
||||
ValueSet result;
|
||||
std::vector<const T*> result;
|
||||
|
||||
// Traverse the tree of values rooted at the representative of the
|
||||
// equivalence class to which |value| belongs, and collect up all the values
|
||||
@ -125,7 +137,7 @@ class EquivalenceRelation {
|
||||
stack.push_back(Find(*value_set_.find(&value)));
|
||||
while (!stack.empty()) {
|
||||
const T* item = stack.back();
|
||||
result.insert(item);
|
||||
result.push_back(item);
|
||||
stack.pop_back();
|
||||
for (auto child : children_[item]) {
|
||||
stack.push_back(child);
|
||||
@ -141,40 +153,45 @@ class EquivalenceRelation {
|
||||
return Find(&value1) == Find(&value2);
|
||||
}
|
||||
|
||||
// Returns the set of all values known to be part of the equivalence relation.
|
||||
ValueSet GetAllKnownValues() const {
|
||||
ValueSet result;
|
||||
// Returns all values known to be part of the equivalence relation.
|
||||
std::vector<const T*> GetAllKnownValues() const {
|
||||
std::vector<const T*> result;
|
||||
for (auto& value : owned_values_) {
|
||||
result.insert(value.get());
|
||||
result.push_back(value.get());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
// Returns true if and only if |value| is known to be part of the equivalence
|
||||
// relation.
|
||||
bool Exists(const T& value) const {
|
||||
return value_set_.find(&value) != value_set_.end();
|
||||
}
|
||||
|
||||
private:
|
||||
// Returns the representative of the equivalence class of |value|, which must
|
||||
// already be known to the equivalence relation. This is the 'Find' operation
|
||||
// in a classic union-find data structure.
|
||||
const T* Find(const T* value) const {
|
||||
assert(Exists(*value));
|
||||
|
||||
// Get the canonical pointer to the value from the value pool.
|
||||
const T* known_value = *value_set_.find(value);
|
||||
assert(parent_[known_value] && "Every known value should have a parent.");
|
||||
|
||||
// Compute the result by chasing parents until we find a value that is its
|
||||
// own parent.
|
||||
const T* result = value;
|
||||
const T* result = known_value;
|
||||
while (parent_[result] != result) {
|
||||
result = parent_[result];
|
||||
}
|
||||
assert(result && "Representatives should never be null.");
|
||||
|
||||
// At this point, |result| is the representative of the equivalence class.
|
||||
// Now perform the 'path compression' optimization by doing another pass up
|
||||
// the parent chain, setting the parent of each node to be the
|
||||
// representative, and rewriting children correspondingly.
|
||||
const T* current = value;
|
||||
const T* current = known_value;
|
||||
while (parent_[current] != result) {
|
||||
const T* next = parent_[current];
|
||||
parent_[current] = result;
|
||||
@ -205,7 +222,7 @@ class EquivalenceRelation {
|
||||
// |owned_values_|, and |value_pool_| provides (via |PointerHashT| and
|
||||
// |PointerEqualsT|) a means for mapping a value of interest to a pointer
|
||||
// into an equivalent value in |owned_values_|.
|
||||
ValueSet value_set_;
|
||||
std::unordered_set<const T*, PointerHashT, PointerEqualsT> value_set_;
|
||||
std::vector<std::unique_ptr<T>> owned_values_;
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "source/fuzz/equivalence_relation.h"
|
||||
#include "source/fuzz/fuzzer_util.h"
|
||||
@ -328,6 +327,10 @@ struct FactManager::DataSynonymFacts {
|
||||
// See method in FactManager which delegates to this method.
|
||||
void AddFact(const protobufs::FactDataSynonym& fact);
|
||||
|
||||
// See method in FactManager which delegates to this method.
|
||||
bool IsSynonymous(const protobufs::DataDescriptor& data_descriptor1,
|
||||
const protobufs::DataDescriptor& data_descriptor2) const;
|
||||
|
||||
EquivalenceRelation<protobufs::DataDescriptor, DataDescriptorHash,
|
||||
DataDescriptorEquals>
|
||||
synonymous;
|
||||
@ -338,6 +341,14 @@ void FactManager::DataSynonymFacts::AddFact(
|
||||
synonymous.MakeEquivalent(fact.data1(), fact.data2());
|
||||
}
|
||||
|
||||
bool FactManager::DataSynonymFacts::IsSynonymous(
|
||||
const protobufs::DataDescriptor& data_descriptor1,
|
||||
const protobufs::DataDescriptor& data_descriptor2) const {
|
||||
return synonymous.Exists(data_descriptor1) &&
|
||||
synonymous.Exists(data_descriptor2) &&
|
||||
synonymous.IsEquivalent(data_descriptor1, data_descriptor2);
|
||||
}
|
||||
|
||||
// End of data synonym facts
|
||||
//==============================
|
||||
|
||||
@ -375,7 +386,8 @@ bool FactManager::AddFact(const fuzz::protobufs::Fact& fact,
|
||||
}
|
||||
|
||||
void FactManager::AddFactDataSynonym(const protobufs::DataDescriptor& data1,
|
||||
const protobufs::DataDescriptor& data2) {
|
||||
const protobufs::DataDescriptor& data2,
|
||||
opt::IRContext* /*unused*/) {
|
||||
protobufs::FactDataSynonym fact;
|
||||
*fact.mutable_data1() = data1;
|
||||
*fact.mutable_data2() = data2;
|
||||
@ -412,27 +424,28 @@ FactManager::GetConstantUniformFactsAndTypes() const {
|
||||
return uniform_constant_facts_->facts_and_type_ids;
|
||||
}
|
||||
|
||||
std::set<uint32_t> FactManager::GetIdsForWhichSynonymsAreKnown() const {
|
||||
std::set<uint32_t> result;
|
||||
std::vector<uint32_t> FactManager::GetIdsForWhichSynonymsAreKnown() const {
|
||||
std::vector<uint32_t> result;
|
||||
for (auto& data_descriptor :
|
||||
data_synonym_facts_->synonymous.GetAllKnownValues()) {
|
||||
if (data_descriptor->index().empty()) {
|
||||
assert(data_descriptor->num_contiguous_elements() == 1 &&
|
||||
"Multiple contiguous elements are only allowed for data "
|
||||
"descriptors that "
|
||||
"are indices into vectors.");
|
||||
result.insert(data_descriptor->object());
|
||||
result.push_back(data_descriptor->object());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unordered_set<const protobufs::DataDescriptor*, DataDescriptorHash,
|
||||
DataDescriptorEquals>
|
||||
FactManager::GetSynonymsForId(uint32_t id) const {
|
||||
std::vector<const protobufs::DataDescriptor*> FactManager::GetSynonymsForId(
|
||||
uint32_t id) const {
|
||||
return data_synonym_facts_->synonymous.GetEquivalenceClass(
|
||||
MakeDataDescriptor(id, {}, 1));
|
||||
MakeDataDescriptor(id, {}));
|
||||
}
|
||||
|
||||
bool FactManager::IsSynonymous(
|
||||
const protobufs::DataDescriptor& data_descriptor1,
|
||||
const protobufs::DataDescriptor& data_descriptor2) const {
|
||||
return data_synonym_facts_->IsSynonymous(data_descriptor1, data_descriptor2);
|
||||
};
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
27
3rdparty/spirv-tools/source/fuzz/fact_manager.h
vendored
27
3rdparty/spirv-tools/source/fuzz/fact_manager.h
vendored
@ -55,7 +55,8 @@ class FactManager {
|
||||
|
||||
// Record the fact that |data1| and |data2| are synonymous.
|
||||
void AddFactDataSynonym(const protobufs::DataDescriptor& data1,
|
||||
const protobufs::DataDescriptor& data2);
|
||||
const protobufs::DataDescriptor& data2,
|
||||
opt::IRContext* context);
|
||||
|
||||
// The fact manager is responsible for managing a few distinct categories of
|
||||
// facts. In principle there could be different fact managers for each kind
|
||||
@ -106,13 +107,17 @@ class FactManager {
|
||||
|
||||
// Returns every id for which a fact of the form "this id is synonymous
|
||||
// with this piece of data" is known.
|
||||
std::set<uint32_t> GetIdsForWhichSynonymsAreKnown() const;
|
||||
std::vector<uint32_t> GetIdsForWhichSynonymsAreKnown() const;
|
||||
|
||||
// Requires that at least one synonym for |id| is known, and returns the
|
||||
// equivalence class of all known synonyms.
|
||||
std::unordered_set<const protobufs::DataDescriptor*, DataDescriptorHash,
|
||||
DataDescriptorEquals>
|
||||
GetSynonymsForId(uint32_t id) const;
|
||||
// Returns the equivalence class of all known synonyms of |id|, or an empty
|
||||
// set if no synonyms are known.
|
||||
std::vector<const protobufs::DataDescriptor*> GetSynonymsForId(
|
||||
uint32_t id) const;
|
||||
|
||||
// Return true if and ony if |data_descriptor1| and |data_descriptor2| are
|
||||
// known to be synonymous.
|
||||
bool IsSynonymous(const protobufs::DataDescriptor& data_descriptor1,
|
||||
const protobufs::DataDescriptor& data_descriptor2) const;
|
||||
|
||||
// End of id synonym facts
|
||||
//==============================
|
||||
@ -121,13 +126,13 @@ class FactManager {
|
||||
// For each distinct kind of fact to be managed, we use a separate opaque
|
||||
// struct type.
|
||||
|
||||
struct ConstantUniformFacts; // Opaque struct for holding data about uniform
|
||||
// buffer elements.
|
||||
struct ConstantUniformFacts; // Opaque class for management of
|
||||
// constant uniform facts.
|
||||
std::unique_ptr<ConstantUniformFacts>
|
||||
uniform_constant_facts_; // Unique pointer to internal data.
|
||||
|
||||
struct DataSynonymFacts; // Opaque struct for holding data about data
|
||||
// synonyms.
|
||||
struct DataSynonymFacts; // Opaque class for management of data synonym
|
||||
// facts.
|
||||
std::unique_ptr<DataSynonymFacts>
|
||||
data_synonym_facts_; // Unique pointer to internal data.
|
||||
};
|
||||
|
@ -82,10 +82,6 @@ message DataDescriptor {
|
||||
// 0 or more indices, used to index into a composite object
|
||||
repeated uint32 index = 2;
|
||||
|
||||
// The number of contiguous elements. This will typically be 1, but e.g. 2 or
|
||||
// 3 can be used to describe the 'xy' or 'xyz' portion of a vec4.
|
||||
uint32 num_contiguous_elements = 3;
|
||||
|
||||
}
|
||||
|
||||
message UniformBufferElementDescriptor {
|
||||
|
@ -133,45 +133,45 @@ void TransformationCompositeConstruct::Apply(opt::IRContext* context,
|
||||
context, SpvOpCompositeConstruct, message_.composite_type_id(),
|
||||
message_.fresh_id(), in_operands));
|
||||
|
||||
fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
|
||||
context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
|
||||
|
||||
// Inform the fact manager that we now have new synonyms: every component of
|
||||
// the composite is synonymous with the id used to construct that component.
|
||||
// the composite is synonymous with the id used to construct that component,
|
||||
// except in the case of a vector where a single vector id can span multiple
|
||||
// components.
|
||||
auto composite_type =
|
||||
context->get_type_mgr()->GetType(message_.composite_type_id());
|
||||
uint32_t index = 0;
|
||||
for (auto component : message_.component()) {
|
||||
// Decide how many contiguous composite elements are represented by the
|
||||
// components. This is always 1, except in the case of a vector that is
|
||||
// constructed by smaller vectors.
|
||||
uint32_t num_contiguous_elements;
|
||||
if (composite_type->AsVector()) {
|
||||
// The vector case is a bit fiddly, because one argument to a vector
|
||||
// constructor can cover more than one element.
|
||||
auto component_type = context->get_type_mgr()->GetType(
|
||||
context->get_def_use_mgr()->GetDef(component)->type_id());
|
||||
if (component_type->AsVector()) {
|
||||
assert(component_type->AsVector()->element_type() ==
|
||||
composite_type->AsVector()->element_type());
|
||||
num_contiguous_elements = component_type->AsVector()->element_count();
|
||||
} else {
|
||||
assert(component_type == composite_type->AsVector()->element_type());
|
||||
num_contiguous_elements = 1;
|
||||
auto component_type = context->get_type_mgr()->GetType(
|
||||
context->get_def_use_mgr()->GetDef(component)->type_id());
|
||||
if (composite_type->AsVector() && component_type->AsVector()) {
|
||||
// The case where the composite being constructed is a vector and the
|
||||
// component provided for construction is also a vector is special. It
|
||||
// requires adding a synonym fact relating each element of the sub-vector
|
||||
// to the corresponding element of the composite being constructed.
|
||||
assert(component_type->AsVector()->element_type() ==
|
||||
composite_type->AsVector()->element_type());
|
||||
assert(component_type->AsVector()->element_count() <
|
||||
composite_type->AsVector()->element_count());
|
||||
for (uint32_t subvector_index = 0;
|
||||
subvector_index < component_type->AsVector()->element_count();
|
||||
subvector_index++) {
|
||||
fact_manager->AddFactDataSynonym(
|
||||
MakeDataDescriptor(component, {subvector_index}),
|
||||
MakeDataDescriptor(message_.fresh_id(), {index}), context);
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
// The non-vector cases are all easy: the constructor has exactly the same
|
||||
// number of arguments as the number of sub-components, so we can just
|
||||
// increment the index.
|
||||
num_contiguous_elements = 1;
|
||||
// The other cases are simple: the component is made directly synonymous
|
||||
// with the element of the composite being constructed.
|
||||
fact_manager->AddFactDataSynonym(
|
||||
MakeDataDescriptor(component, {}),
|
||||
MakeDataDescriptor(message_.fresh_id(), {index}), context);
|
||||
index++;
|
||||
}
|
||||
|
||||
fact_manager->AddFactDataSynonym(
|
||||
MakeDataDescriptor(component, {}, 1),
|
||||
MakeDataDescriptor(message_.fresh_id(), {index},
|
||||
num_contiguous_elements));
|
||||
index += num_contiguous_elements;
|
||||
}
|
||||
|
||||
fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
|
||||
context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
|
||||
}
|
||||
|
||||
bool TransformationCompositeConstruct::ComponentsForArrayConstructionAreOK(
|
||||
|
@ -106,11 +106,11 @@ void TransformationCompositeExtract::Apply(
|
||||
indices.push_back(an_index);
|
||||
}
|
||||
protobufs::DataDescriptor data_descriptor_for_extracted_element =
|
||||
MakeDataDescriptor(message_.composite_id(), std::move(indices), 1);
|
||||
MakeDataDescriptor(message_.composite_id(), std::move(indices));
|
||||
protobufs::DataDescriptor data_descriptor_for_result_id =
|
||||
MakeDataDescriptor(message_.fresh_id(), {}, 1);
|
||||
MakeDataDescriptor(message_.fresh_id(), {});
|
||||
fact_manager->AddFactDataSynonym(data_descriptor_for_extracted_element,
|
||||
data_descriptor_for_result_id);
|
||||
data_descriptor_for_result_id, context);
|
||||
}
|
||||
|
||||
protobufs::Transformation TransformationCompositeExtract::ToMessage() const {
|
||||
|
@ -102,9 +102,9 @@ void TransformationCopyObject::Apply(opt::IRContext* context,
|
||||
fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
|
||||
context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
|
||||
|
||||
fact_manager->AddFactDataSynonym(
|
||||
MakeDataDescriptor(message_.object(), {}, 1),
|
||||
MakeDataDescriptor(message_.fresh_id(), {}, 1));
|
||||
fact_manager->AddFactDataSynonym(MakeDataDescriptor(message_.object(), {}),
|
||||
MakeDataDescriptor(message_.fresh_id(), {}),
|
||||
context);
|
||||
}
|
||||
|
||||
protobufs::Transformation TransformationCopyObject::ToMessage() const {
|
||||
|
@ -46,8 +46,9 @@ bool TransformationReplaceIdWithSynonym::IsApplicable(
|
||||
auto id_of_interest = message_.id_use_descriptor().id_of_interest();
|
||||
|
||||
// Does the fact manager know about the synonym?
|
||||
if (fact_manager.GetIdsForWhichSynonymsAreKnown().count(id_of_interest) ==
|
||||
0) {
|
||||
auto ids_with_known_synonyms = fact_manager.GetIdsForWhichSynonymsAreKnown();
|
||||
if (std::find(ids_with_known_synonyms.begin(), ids_with_known_synonyms.end(),
|
||||
id_of_interest) == ids_with_known_synonyms.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -160,7 +160,6 @@
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
using opt::BasicBlock;
|
||||
using opt::Instruction;
|
||||
using opt::Operand;
|
||||
using spvtools::MakeUnique;
|
||||
|
@ -81,8 +81,8 @@ class GraphicsRobustAccessPass : public Pass {
|
||||
// sign extension or zero extension. The new instruction is inserted
|
||||
// immediately before |before_inst|, and is analyzed for definitions and uses.
|
||||
// Returns the newly inserted instruction. Assumes the |value| is an integer
|
||||
// scalar of a narrower type than |bitwidth| bits.
|
||||
Instruction* WidenInteger(bool sign_extend, uint32_t bitwidth,
|
||||
// scalar of a narrower type than |bit_width| bits.
|
||||
Instruction* WidenInteger(bool sign_extend, uint32_t bit_width,
|
||||
Instruction* value, Instruction* before_inst);
|
||||
|
||||
// Returns a new instruction that invokes the UClamp GLSL.std.450 extended
|
||||
@ -109,7 +109,8 @@ class GraphicsRobustAccessPass : public Pass {
|
||||
// the module is modified. Returns a status code to indicate success
|
||||
// or failure. If assumptions are not met, returns an error status code
|
||||
// and emits a diagnostic.
|
||||
spv_result_t ClampCoordinateForImageTexelPointer(opt::Instruction* itp);
|
||||
spv_result_t ClampCoordinateForImageTexelPointer(
|
||||
opt::Instruction* image_texel_pointer);
|
||||
|
||||
// Gets the instruction that defines the given id.
|
||||
opt::Instruction* GetDef(uint32_t id) {
|
||||
|
21
3rdparty/spirv-tools/source/opt/optimizer.cpp
vendored
21
3rdparty/spirv-tools/source/opt/optimizer.cpp
vendored
@ -560,23 +560,26 @@ bool Optimizer::Run(const uint32_t* original_binary,
|
||||
return false;
|
||||
}
|
||||
|
||||
optimized_binary->clear();
|
||||
context->module()->ToBinary(optimized_binary, /* skip_nop = */ true);
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (status == opt::Pass::Status::SuccessWithoutChange) {
|
||||
std::vector<uint32_t> optimized_binary_with_nop;
|
||||
context->module()->ToBinary(&optimized_binary_with_nop,
|
||||
/* skip_nop = */ false);
|
||||
auto changed = optimized_binary_with_nop.size() != original_binary_size ||
|
||||
memcmp(optimized_binary_with_nop.data(), original_binary,
|
||||
original_binary_size) != 0;
|
||||
assert(!changed &&
|
||||
"Binary unexpectedly changed despite optimizer saying there was no "
|
||||
"change");
|
||||
assert(optimized_binary_with_nop.size() == original_binary_size &&
|
||||
"Binary size unexpectedly changed despite the optimizer saying "
|
||||
"there was no change");
|
||||
assert(memcmp(optimized_binary_with_nop.data(), original_binary,
|
||||
original_binary_size) == 0 &&
|
||||
"Binary content unexpectedly changed despite the optimizer saying "
|
||||
"there was no change");
|
||||
}
|
||||
#endif // !NDEBUG
|
||||
|
||||
// Note that |original_binary| and |optimized_binary| may share the same
|
||||
// buffer and the below will invalidate |original_binary|.
|
||||
optimized_binary->clear();
|
||||
context->module()->ToBinary(optimized_binary, /* skip_nop = */ true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
2
3rdparty/spirv-tools/source/print.cpp
vendored
2
3rdparty/spirv-tools/source/print.cpp
vendored
@ -15,7 +15,7 @@
|
||||
#include "source/print.h"
|
||||
|
||||
#if defined(SPIRV_ANDROID) || defined(SPIRV_LINUX) || defined(SPIRV_MAC) || \
|
||||
defined(SPIRV_FREEBSD) || defined(SPIRV_EMSCRIPTEN)
|
||||
defined(SPIRV_IOS) || defined(SPIRV_FREEBSD) || defined(SPIRV_EMSCRIPTEN)
|
||||
namespace spvtools {
|
||||
|
||||
clr::reset::operator const char*() { return "\x1b[0m"; }
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "source/fuzz/equivalence_relation.h"
|
||||
|
||||
@ -33,12 +34,11 @@ struct UInt32Hash {
|
||||
}
|
||||
};
|
||||
|
||||
std::set<uint32_t> ToUIntSet(
|
||||
EquivalenceRelation<uint32_t, UInt32Hash, UInt32Equals>::ValueSet
|
||||
pointers) {
|
||||
std::set<uint32_t> result;
|
||||
std::vector<uint32_t> ToUIntVector(
|
||||
const std::vector<const uint32_t*>& pointers) {
|
||||
std::vector<uint32_t> result;
|
||||
for (auto pointer : pointers) {
|
||||
result.insert(*pointer);
|
||||
result.push_back(*pointer);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -59,38 +59,63 @@ TEST(EquivalenceRelationTest, BasicTest) {
|
||||
|
||||
relation.MakeEquivalent(78, 80);
|
||||
|
||||
std::set<uint32_t> class1;
|
||||
std::vector<uint32_t> class1;
|
||||
for (uint32_t element = 0; element < 98; element += 2) {
|
||||
ASSERT_TRUE(relation.IsEquivalent(0, element));
|
||||
ASSERT_TRUE(relation.IsEquivalent(element, element + 2));
|
||||
class1.insert(element);
|
||||
class1.push_back(element);
|
||||
}
|
||||
class1.insert(98);
|
||||
ASSERT_TRUE(class1 == ToUIntSet(relation.GetEquivalenceClass(0)));
|
||||
ASSERT_TRUE(class1 == ToUIntSet(relation.GetEquivalenceClass(4)));
|
||||
ASSERT_TRUE(class1 == ToUIntSet(relation.GetEquivalenceClass(40)));
|
||||
class1.push_back(98);
|
||||
|
||||
std::set<uint32_t> class2;
|
||||
ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(0)),
|
||||
testing::WhenSorted(class1));
|
||||
ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(4)),
|
||||
testing::WhenSorted(class1));
|
||||
ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(40)),
|
||||
testing::WhenSorted(class1));
|
||||
|
||||
std::vector<uint32_t> class2;
|
||||
for (uint32_t element = 1; element < 79; element += 2) {
|
||||
ASSERT_TRUE(relation.IsEquivalent(1, element));
|
||||
ASSERT_TRUE(relation.IsEquivalent(element, element + 2));
|
||||
class2.insert(element);
|
||||
class2.push_back(element);
|
||||
}
|
||||
class2.insert(79);
|
||||
ASSERT_TRUE(class2 == ToUIntSet(relation.GetEquivalenceClass(1)));
|
||||
ASSERT_TRUE(class2 == ToUIntSet(relation.GetEquivalenceClass(11)));
|
||||
ASSERT_TRUE(class2 == ToUIntSet(relation.GetEquivalenceClass(31)));
|
||||
class2.push_back(79);
|
||||
ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(1)),
|
||||
testing::WhenSorted(class2));
|
||||
ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(11)),
|
||||
testing::WhenSorted(class2));
|
||||
ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(31)),
|
||||
testing::WhenSorted(class2));
|
||||
|
||||
std::set<uint32_t> class3;
|
||||
std::vector<uint32_t> class3;
|
||||
for (uint32_t element = 81; element < 99; element += 2) {
|
||||
ASSERT_TRUE(relation.IsEquivalent(81, element));
|
||||
ASSERT_TRUE(relation.IsEquivalent(element, element + 2));
|
||||
class3.insert(element);
|
||||
class3.push_back(element);
|
||||
}
|
||||
class3.push_back(99);
|
||||
ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(81)),
|
||||
testing::WhenSorted(class3));
|
||||
ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(91)),
|
||||
testing::WhenSorted(class3));
|
||||
ASSERT_THAT(ToUIntVector(relation.GetEquivalenceClass(99)),
|
||||
testing::WhenSorted(class3));
|
||||
|
||||
bool first = true;
|
||||
std::vector<const uint32_t*> previous_class;
|
||||
for (auto representative : relation.GetEquivalenceClassRepresentatives()) {
|
||||
std::vector<const uint32_t*> current_class =
|
||||
relation.GetEquivalenceClass(*representative);
|
||||
ASSERT_TRUE(std::find(current_class.begin(), current_class.end(),
|
||||
representative) != current_class.end());
|
||||
if (!first) {
|
||||
ASSERT_TRUE(std::find(previous_class.begin(), previous_class.end(),
|
||||
representative) == previous_class.end());
|
||||
}
|
||||
previous_class = current_class;
|
||||
first = false;
|
||||
}
|
||||
class3.insert(99);
|
||||
ASSERT_TRUE(class3 == ToUIntSet(relation.GetEquivalenceClass(81)));
|
||||
ASSERT_TRUE(class3 == ToUIntSet(relation.GetEquivalenceClass(91)));
|
||||
ASSERT_TRUE(class3 == ToUIntSet(relation.GetEquivalenceClass(99)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -21,21 +21,6 @@ namespace spvtools {
|
||||
namespace fuzz {
|
||||
namespace {
|
||||
|
||||
bool SynonymFactHolds(const FactManager& fact_manager, uint32_t id,
|
||||
uint32_t synonym_base_id,
|
||||
std::vector<uint32_t>&& synonym_indices) {
|
||||
if (fact_manager.GetIdsForWhichSynonymsAreKnown().count(id) == 0) {
|
||||
return false;
|
||||
}
|
||||
auto synonyms = fact_manager.GetSynonymsForId(id);
|
||||
auto temp =
|
||||
MakeDataDescriptor(synonym_base_id, std::move(synonym_indices), 1);
|
||||
return std::find_if(synonyms.begin(), synonyms.end(),
|
||||
[&temp](const protobufs::DataDescriptor* dd) -> bool {
|
||||
return DataDescriptorEquals()(dd, &temp);
|
||||
}) != synonyms.end();
|
||||
}
|
||||
|
||||
TEST(TransformationCompositeConstructTest, ConstructArrays) {
|
||||
std::string shader = R"(
|
||||
OpCapability Shader
|
||||
@ -159,9 +144,12 @@ TEST(TransformationCompositeConstructTest, ConstructArrays) {
|
||||
make_vec2_array_length_3_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_vec2_array_length_3.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 41, 200, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 45, 200, {1}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 27, 200, {2}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(41, {}),
|
||||
MakeDataDescriptor(200, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(45, {}),
|
||||
MakeDataDescriptor(200, {1})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {}),
|
||||
MakeDataDescriptor(200, {2})));
|
||||
|
||||
// Make a float[2]
|
||||
TransformationCompositeConstruct make_float_array_length_2(
|
||||
@ -175,8 +163,10 @@ TEST(TransformationCompositeConstructTest, ConstructArrays) {
|
||||
make_float_array_length_2_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_float_array_length_2.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 24, 201, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 40, 201, {1}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(24, {}),
|
||||
MakeDataDescriptor(201, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(40, {}),
|
||||
MakeDataDescriptor(201, {1})));
|
||||
|
||||
// Make a bool[3]
|
||||
TransformationCompositeConstruct make_bool_array_length_3(
|
||||
@ -192,9 +182,12 @@ TEST(TransformationCompositeConstructTest, ConstructArrays) {
|
||||
make_bool_array_length_3_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_bool_array_length_3.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 33, 202, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 50, 202, {1}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 50, 202, {2}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {}),
|
||||
MakeDataDescriptor(202, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(50, {}),
|
||||
MakeDataDescriptor(202, {1})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(50, {}),
|
||||
MakeDataDescriptor(202, {2})));
|
||||
|
||||
// make a uvec3[2][2]
|
||||
TransformationCompositeConstruct make_uvec3_array_length_2_2(
|
||||
@ -208,8 +201,10 @@ TEST(TransformationCompositeConstructTest, ConstructArrays) {
|
||||
fact_manager));
|
||||
make_uvec3_array_length_2_2.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 69, 203, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 100, 203, {1}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(69, {}),
|
||||
MakeDataDescriptor(203, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(100, {}),
|
||||
MakeDataDescriptor(203, {1})));
|
||||
|
||||
std::string after_transformation = R"(
|
||||
OpCapability Shader
|
||||
@ -408,9 +403,12 @@ TEST(TransformationCompositeConstructTest, ConstructMatrices) {
|
||||
ASSERT_FALSE(make_mat34_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_mat34.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 25, 200, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 28, 200, {1}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 31, 200, {2}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(25, {}),
|
||||
MakeDataDescriptor(200, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(28, {}),
|
||||
MakeDataDescriptor(200, {1})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(31, {}),
|
||||
MakeDataDescriptor(200, {2})));
|
||||
|
||||
// make a mat4x3
|
||||
TransformationCompositeConstruct make_mat43(
|
||||
@ -422,10 +420,14 @@ TEST(TransformationCompositeConstructTest, ConstructMatrices) {
|
||||
ASSERT_FALSE(make_mat43_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_mat43.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 11, 201, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 13, 201, {1}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 16, 201, {2}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 100, 201, {3}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(11, {}),
|
||||
MakeDataDescriptor(201, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(13, {}),
|
||||
MakeDataDescriptor(201, {1})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(16, {}),
|
||||
MakeDataDescriptor(201, {2})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(100, {}),
|
||||
MakeDataDescriptor(201, {3})));
|
||||
|
||||
std::string after_transformation = R"(
|
||||
OpCapability Shader
|
||||
@ -609,8 +611,10 @@ TEST(TransformationCompositeConstructTest, ConstructStructs) {
|
||||
ASSERT_FALSE(make_inner_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_inner.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 25, 200, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 19, 200, {1}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(25, {}),
|
||||
MakeDataDescriptor(200, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(19, {}),
|
||||
MakeDataDescriptor(200, {1})));
|
||||
|
||||
// make an Outer
|
||||
TransformationCompositeConstruct make_outer(
|
||||
@ -624,9 +628,12 @@ TEST(TransformationCompositeConstructTest, ConstructStructs) {
|
||||
ASSERT_FALSE(make_outer_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_outer.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 46, 201, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 200, 201, {1}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 56, 201, {2}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(46, {}),
|
||||
MakeDataDescriptor(201, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(200, {}),
|
||||
MakeDataDescriptor(201, {1})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(56, {}),
|
||||
MakeDataDescriptor(201, {2})));
|
||||
|
||||
std::string after_transformation = R"(
|
||||
OpCapability Shader
|
||||
@ -922,8 +929,10 @@ TEST(TransformationCompositeConstructTest, ConstructVectors) {
|
||||
ASSERT_FALSE(make_vec2_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_vec2.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 17, 200, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 11, 200, {1}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
|
||||
MakeDataDescriptor(200, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(11, {}),
|
||||
MakeDataDescriptor(200, {1})));
|
||||
|
||||
TransformationCompositeConstruct make_vec3(
|
||||
25, {12, 32}, MakeInstructionDescriptor(35, SpvOpCompositeConstruct, 0),
|
||||
@ -936,8 +945,12 @@ TEST(TransformationCompositeConstructTest, ConstructVectors) {
|
||||
ASSERT_FALSE(make_vec3_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_vec3.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 12, 201, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 32, 201, {2}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(12, {0}),
|
||||
MakeDataDescriptor(201, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(12, {1}),
|
||||
MakeDataDescriptor(201, {1})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(32, {}),
|
||||
MakeDataDescriptor(201, {2})));
|
||||
|
||||
TransformationCompositeConstruct make_vec4(
|
||||
44, {32, 32, 10, 11}, MakeInstructionDescriptor(75, SpvOpAccessChain, 0),
|
||||
@ -950,10 +963,14 @@ TEST(TransformationCompositeConstructTest, ConstructVectors) {
|
||||
ASSERT_FALSE(make_vec4_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_vec4.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 32, 202, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 32, 202, {1}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 10, 202, {2}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 11, 202, {3}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(32, {}),
|
||||
MakeDataDescriptor(202, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(32, {}),
|
||||
MakeDataDescriptor(202, {1})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(10, {}),
|
||||
MakeDataDescriptor(202, {2})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(11, {}),
|
||||
MakeDataDescriptor(202, {3})));
|
||||
|
||||
TransformationCompositeConstruct make_ivec2(
|
||||
51, {126, 120}, MakeInstructionDescriptor(128, SpvOpLoad, 0), 203);
|
||||
@ -964,8 +981,10 @@ TEST(TransformationCompositeConstructTest, ConstructVectors) {
|
||||
ASSERT_FALSE(make_ivec2_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_ivec2.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 126, 203, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 120, 203, {1}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(126, {}),
|
||||
MakeDataDescriptor(203, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(120, {}),
|
||||
MakeDataDescriptor(203, {1})));
|
||||
|
||||
TransformationCompositeConstruct make_ivec3(
|
||||
114, {56, 117, 56}, MakeInstructionDescriptor(66, SpvOpAccessChain, 0),
|
||||
@ -978,9 +997,12 @@ TEST(TransformationCompositeConstructTest, ConstructVectors) {
|
||||
ASSERT_FALSE(make_ivec3_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_ivec3.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 56, 204, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 117, 204, {1}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 56, 204, {2}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(56, {}),
|
||||
MakeDataDescriptor(204, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(117, {}),
|
||||
MakeDataDescriptor(204, {1})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(56, {}),
|
||||
MakeDataDescriptor(204, {2})));
|
||||
|
||||
TransformationCompositeConstruct make_ivec4(
|
||||
122, {56, 117, 117, 117}, MakeInstructionDescriptor(66, SpvOpIAdd, 0),
|
||||
@ -993,10 +1015,14 @@ TEST(TransformationCompositeConstructTest, ConstructVectors) {
|
||||
ASSERT_FALSE(make_ivec4_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_ivec4.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 56, 205, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 117, 205, {1}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 117, 205, {2}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 117, 205, {3}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(56, {}),
|
||||
MakeDataDescriptor(205, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(117, {}),
|
||||
MakeDataDescriptor(205, {1})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(117, {}),
|
||||
MakeDataDescriptor(205, {2})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(117, {}),
|
||||
MakeDataDescriptor(205, {3})));
|
||||
|
||||
TransformationCompositeConstruct make_uvec2(
|
||||
86, {18, 38}, MakeInstructionDescriptor(133, SpvOpAccessChain, 0), 206);
|
||||
@ -1006,8 +1032,10 @@ TEST(TransformationCompositeConstructTest, ConstructVectors) {
|
||||
ASSERT_FALSE(make_uvec2_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_uvec2.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 18, 206, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 38, 206, {1}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(18, {}),
|
||||
MakeDataDescriptor(206, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(38, {}),
|
||||
MakeDataDescriptor(206, {1})));
|
||||
|
||||
TransformationCompositeConstruct make_uvec3(
|
||||
59, {14, 18, 136}, MakeInstructionDescriptor(137, SpvOpReturn, 0), 207);
|
||||
@ -1018,9 +1046,12 @@ TEST(TransformationCompositeConstructTest, ConstructVectors) {
|
||||
ASSERT_FALSE(make_uvec3_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_uvec3.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 14, 207, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 18, 207, {1}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 136, 207, {2}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(14, {}),
|
||||
MakeDataDescriptor(207, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(18, {}),
|
||||
MakeDataDescriptor(207, {1})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(136, {}),
|
||||
MakeDataDescriptor(207, {2})));
|
||||
|
||||
TransformationCompositeConstruct make_uvec4(
|
||||
131, {14, 18, 136, 136},
|
||||
@ -1033,10 +1064,14 @@ TEST(TransformationCompositeConstructTest, ConstructVectors) {
|
||||
ASSERT_FALSE(make_uvec4_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_uvec4.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 14, 208, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 18, 208, {1}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 136, 208, {2}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 136, 208, {3}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(14, {}),
|
||||
MakeDataDescriptor(208, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(18, {}),
|
||||
MakeDataDescriptor(208, {1})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(136, {}),
|
||||
MakeDataDescriptor(208, {2})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(136, {}),
|
||||
MakeDataDescriptor(208, {3})));
|
||||
|
||||
TransformationCompositeConstruct make_bvec2(
|
||||
102,
|
||||
@ -1057,8 +1092,10 @@ TEST(TransformationCompositeConstructTest, ConstructVectors) {
|
||||
ASSERT_FALSE(make_bvec2_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_bvec2.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 111, 209, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 41, 209, {1}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(111, {}),
|
||||
MakeDataDescriptor(209, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(41, {}),
|
||||
MakeDataDescriptor(209, {1})));
|
||||
|
||||
TransformationCompositeConstruct make_bvec3(
|
||||
93, {108, 73}, MakeInstructionDescriptor(108, SpvOpStore, 0), 210);
|
||||
@ -1069,8 +1106,12 @@ TEST(TransformationCompositeConstructTest, ConstructVectors) {
|
||||
ASSERT_FALSE(make_bvec3_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_bvec3.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 108, 210, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 73, 210, {2}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {0}),
|
||||
MakeDataDescriptor(210, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {1}),
|
||||
MakeDataDescriptor(210, {1})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(73, {}),
|
||||
MakeDataDescriptor(210, {2})));
|
||||
|
||||
TransformationCompositeConstruct make_bvec4(
|
||||
70, {108, 108}, MakeInstructionDescriptor(108, SpvOpBranch, 0), 211);
|
||||
@ -1081,8 +1122,14 @@ TEST(TransformationCompositeConstructTest, ConstructVectors) {
|
||||
ASSERT_FALSE(make_bvec4_bad.IsApplicable(context.get(), fact_manager));
|
||||
make_bvec4.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 108, 211, {0}));
|
||||
ASSERT_TRUE(SynonymFactHolds(fact_manager, 108, 211, {2}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {0}),
|
||||
MakeDataDescriptor(211, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {1}),
|
||||
MakeDataDescriptor(211, {1})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {0}),
|
||||
MakeDataDescriptor(211, {2})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(108, {1}),
|
||||
MakeDataDescriptor(211, {3})));
|
||||
|
||||
std::string after_transformation = R"(
|
||||
OpCapability Shader
|
||||
|
@ -20,13 +20,6 @@ namespace spvtools {
|
||||
namespace fuzz {
|
||||
namespace {
|
||||
|
||||
bool IsSynonymous(const FactManager& fact_manager, uint32_t id,
|
||||
uint32_t composite_id, std::vector<uint32_t>&& indices) {
|
||||
protobufs::DataDescriptor data_descriptor =
|
||||
MakeDataDescriptor(composite_id, std::move(indices), 1);
|
||||
return fact_manager.GetSynonymsForId(id).count(&data_descriptor) == 1;
|
||||
}
|
||||
|
||||
TEST(TransformationCompositeExtractTest, BasicTest) {
|
||||
std::string shader = R"(
|
||||
OpCapability Shader
|
||||
@ -179,12 +172,18 @@ TEST(TransformationCompositeExtractTest, BasicTest) {
|
||||
transformation_6.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
ASSERT_TRUE(IsSynonymous(fact_manager, 201, 100, {2}));
|
||||
ASSERT_TRUE(IsSynonymous(fact_manager, 202, 104, {0, 2}));
|
||||
ASSERT_TRUE(IsSynonymous(fact_manager, 203, 104, {0}));
|
||||
ASSERT_TRUE(IsSynonymous(fact_manager, 204, 101, {0}));
|
||||
ASSERT_TRUE(IsSynonymous(fact_manager, 205, 102, {2}));
|
||||
ASSERT_TRUE(IsSynonymous(fact_manager, 206, 103, {1}));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(201, {}),
|
||||
MakeDataDescriptor(100, {2})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(202, {}),
|
||||
MakeDataDescriptor(104, {0, 2})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(203, {}),
|
||||
MakeDataDescriptor(104, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(204, {}),
|
||||
MakeDataDescriptor(101, {0})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(205, {}),
|
||||
MakeDataDescriptor(102, {2})));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(206, {}),
|
||||
MakeDataDescriptor(103, {1})));
|
||||
|
||||
std::string after_transformation = R"(
|
||||
OpCapability Shader
|
||||
|
@ -60,14 +60,16 @@ TEST(TransformationCopyObjectTest, CopyBooleanConstants) {
|
||||
ASSERT_TRUE(copy_true.IsApplicable(context.get(), fact_manager));
|
||||
copy_true.Apply(context.get(), &fact_manager);
|
||||
|
||||
std::set<uint32_t> ids_for_which_synonyms_are_known =
|
||||
auto ids_for_which_synonyms_are_known =
|
||||
fact_manager.GetIdsForWhichSynonymsAreKnown();
|
||||
ASSERT_EQ(2, ids_for_which_synonyms_are_known.size());
|
||||
ASSERT_TRUE(ids_for_which_synonyms_are_known.find(7) !=
|
||||
ids_for_which_synonyms_are_known.end());
|
||||
ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(),
|
||||
ids_for_which_synonyms_are_known.end(),
|
||||
7) != ids_for_which_synonyms_are_known.end());
|
||||
ASSERT_EQ(2, fact_manager.GetSynonymsForId(7).size());
|
||||
protobufs::DataDescriptor descriptor_100 = MakeDataDescriptor(100, {}, 1);
|
||||
ASSERT_TRUE(fact_manager.GetSynonymsForId(7).count(&descriptor_100) > 0);
|
||||
protobufs::DataDescriptor descriptor_100 = MakeDataDescriptor(100, {});
|
||||
ASSERT_TRUE(
|
||||
fact_manager.IsSynonymous(MakeDataDescriptor(7, {}), descriptor_100));
|
||||
}
|
||||
|
||||
{
|
||||
@ -75,14 +77,16 @@ TEST(TransformationCopyObjectTest, CopyBooleanConstants) {
|
||||
8, MakeInstructionDescriptor(100, SpvOpReturn, 0), 101);
|
||||
ASSERT_TRUE(copy_false.IsApplicable(context.get(), fact_manager));
|
||||
copy_false.Apply(context.get(), &fact_manager);
|
||||
std::set<uint32_t> ids_for_which_synonyms_are_known =
|
||||
auto ids_for_which_synonyms_are_known =
|
||||
fact_manager.GetIdsForWhichSynonymsAreKnown();
|
||||
ASSERT_EQ(4, ids_for_which_synonyms_are_known.size());
|
||||
ASSERT_TRUE(ids_for_which_synonyms_are_known.find(8) !=
|
||||
ids_for_which_synonyms_are_known.end());
|
||||
ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(),
|
||||
ids_for_which_synonyms_are_known.end(),
|
||||
8) != ids_for_which_synonyms_are_known.end());
|
||||
ASSERT_EQ(2, fact_manager.GetSynonymsForId(8).size());
|
||||
protobufs::DataDescriptor descriptor_101 = MakeDataDescriptor(101, {}, 1);
|
||||
ASSERT_TRUE(fact_manager.GetSynonymsForId(8).count(&descriptor_101) > 0);
|
||||
protobufs::DataDescriptor descriptor_101 = MakeDataDescriptor(101, {});
|
||||
ASSERT_TRUE(
|
||||
fact_manager.IsSynonymous(MakeDataDescriptor(8, {}), descriptor_101));
|
||||
}
|
||||
|
||||
{
|
||||
@ -90,14 +94,16 @@ TEST(TransformationCopyObjectTest, CopyBooleanConstants) {
|
||||
101, MakeInstructionDescriptor(5, SpvOpReturn, 0), 102);
|
||||
ASSERT_TRUE(copy_false_again.IsApplicable(context.get(), fact_manager));
|
||||
copy_false_again.Apply(context.get(), &fact_manager);
|
||||
std::set<uint32_t> ids_for_which_synonyms_are_known =
|
||||
auto ids_for_which_synonyms_are_known =
|
||||
fact_manager.GetIdsForWhichSynonymsAreKnown();
|
||||
ASSERT_EQ(5, ids_for_which_synonyms_are_known.size());
|
||||
ASSERT_TRUE(ids_for_which_synonyms_are_known.find(101) !=
|
||||
ids_for_which_synonyms_are_known.end());
|
||||
ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(),
|
||||
ids_for_which_synonyms_are_known.end(),
|
||||
101) != ids_for_which_synonyms_are_known.end());
|
||||
ASSERT_EQ(3, fact_manager.GetSynonymsForId(101).size());
|
||||
protobufs::DataDescriptor descriptor_102 = MakeDataDescriptor(102, {}, 1);
|
||||
ASSERT_TRUE(fact_manager.GetSynonymsForId(101).count(&descriptor_102) > 0);
|
||||
protobufs::DataDescriptor descriptor_102 = MakeDataDescriptor(102, {});
|
||||
ASSERT_TRUE(
|
||||
fact_manager.IsSynonymous(MakeDataDescriptor(101, {}), descriptor_102));
|
||||
}
|
||||
|
||||
{
|
||||
@ -105,14 +111,16 @@ TEST(TransformationCopyObjectTest, CopyBooleanConstants) {
|
||||
7, MakeInstructionDescriptor(102, SpvOpReturn, 0), 103);
|
||||
ASSERT_TRUE(copy_true_again.IsApplicable(context.get(), fact_manager));
|
||||
copy_true_again.Apply(context.get(), &fact_manager);
|
||||
std::set<uint32_t> ids_for_which_synonyms_are_known =
|
||||
auto ids_for_which_synonyms_are_known =
|
||||
fact_manager.GetIdsForWhichSynonymsAreKnown();
|
||||
ASSERT_EQ(6, ids_for_which_synonyms_are_known.size());
|
||||
ASSERT_TRUE(ids_for_which_synonyms_are_known.find(7) !=
|
||||
ids_for_which_synonyms_are_known.end());
|
||||
ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(),
|
||||
ids_for_which_synonyms_are_known.end(),
|
||||
7) != ids_for_which_synonyms_are_known.end());
|
||||
ASSERT_EQ(3, fact_manager.GetSynonymsForId(7).size());
|
||||
protobufs::DataDescriptor descriptor_103 = MakeDataDescriptor(103, {}, 1);
|
||||
ASSERT_TRUE(fact_manager.GetSynonymsForId(7).count(&descriptor_103) > 0);
|
||||
protobufs::DataDescriptor descriptor_103 = MakeDataDescriptor(103, {});
|
||||
ASSERT_TRUE(
|
||||
fact_manager.IsSynonymous(MakeDataDescriptor(7, {}), descriptor_103));
|
||||
}
|
||||
|
||||
std::string after_transformation = R"(
|
||||
|
@ -55,8 +55,15 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
options++) {
|
||||
spvBinaryToText(context, input.data(), input.size(), options, &text,
|
||||
&diagnostic);
|
||||
if (diagnostic) spvDiagnosticDestroy(diagnostic);
|
||||
if (text) spvTextDestroy(text);
|
||||
if (diagnostic) {
|
||||
spvDiagnosticDestroy(diagnostic);
|
||||
diagnostic = nullptr;
|
||||
}
|
||||
|
||||
if (text) {
|
||||
spvTextDestroy(text);
|
||||
text = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
spvContextDestroy(context);
|
||||
|
@ -199,11 +199,11 @@ std::string ACCheck(const std::string& access_chain_inst,
|
||||
const std::string& original,
|
||||
const std::string& transformed) {
|
||||
return "\n ; CHECK: %ac = " + access_chain_inst + " %ptr_ty %var" +
|
||||
(transformed.size() ? " " : "") + transformed +
|
||||
(transformed.empty() ? "" : " ") + transformed +
|
||||
"\n ; CHECK-NOT: " + access_chain_inst +
|
||||
"\n ; CHECK-NEXT: OpReturn"
|
||||
"\n %ac = " +
|
||||
access_chain_inst + " %ptr_ty %var " + (original.size() ? " " : "") +
|
||||
access_chain_inst + " %ptr_ty %var " + (original.empty() ? "" : " ") +
|
||||
original + "\n";
|
||||
}
|
||||
|
||||
@ -211,11 +211,11 @@ std::string ACCheckFail(const std::string& access_chain_inst,
|
||||
const std::string& original,
|
||||
const std::string& transformed) {
|
||||
return "\n ; CHECK: %ac = " + access_chain_inst + " %ptr_ty %var" +
|
||||
(transformed.size() ? " " : "") + transformed +
|
||||
(transformed.empty() ? "" : " ") + transformed +
|
||||
"\n ; CHECK-NOT: " + access_chain_inst +
|
||||
"\n ; CHECK-NOT: OpReturn"
|
||||
"\n %ac = " +
|
||||
access_chain_inst + " %ptr_ty %var " + (original.size() ? " " : "") +
|
||||
access_chain_inst + " %ptr_ty %var " + (original.empty() ? "" : " ") +
|
||||
original + "\n";
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ def describe(directory):
|
||||
# e.g. because the source tree might not be in a git tree.
|
||||
# In this case, usually use a timestamp. However, to ensure
|
||||
# reproducible builds, allow the builder to override the wall
|
||||
# clock time with enviornment variable SOURCE_DATE_EPOCH
|
||||
# clock time with environment variable SOURCE_DATE_EPOCH
|
||||
# containing a (presumably) fixed timestamp.
|
||||
timestamp = int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))
|
||||
formatted = datetime.datetime.utcfromtimestamp(timestamp).isoformat()
|
||||
|
@ -18,7 +18,7 @@
|
||||
"id": "spirv",
|
||||
"configuration": "spirv.configuration.json",
|
||||
"extensions": [
|
||||
"spirv"
|
||||
"spvasm"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user