ソースを参照

Updated spirv-tools.

Бранимир Караџић 6 年 前
コミット
274757090d
24 ファイル変更397 行追加233 行削除
  1. 26 1
      3rdparty/spirv-tools/BUILD.gn
  2. 1 1
      3rdparty/spirv-tools/include/generated/build-version.inc
  3. 18 3
      3rdparty/spirv-tools/source/fuzz/data_descriptor.cpp
  4. 5 2
      3rdparty/spirv-tools/source/fuzz/data_descriptor.h
  5. 30 13
      3rdparty/spirv-tools/source/fuzz/equivalence_relation.h
  6. 26 13
      3rdparty/spirv-tools/source/fuzz/fact_manager.cpp
  7. 16 11
      3rdparty/spirv-tools/source/fuzz/fact_manager.h
  8. 0 4
      3rdparty/spirv-tools/source/fuzz/protobufs/spvtoolsfuzz.proto
  9. 30 30
      3rdparty/spirv-tools/source/fuzz/transformation_composite_construct.cpp
  10. 3 3
      3rdparty/spirv-tools/source/fuzz/transformation_composite_extract.cpp
  11. 3 3
      3rdparty/spirv-tools/source/fuzz/transformation_copy_object.cpp
  12. 3 2
      3rdparty/spirv-tools/source/fuzz/transformation_replace_id_with_synonym.cpp
  13. 0 1
      3rdparty/spirv-tools/source/opt/graphics_robust_access_pass.cpp
  14. 4 3
      3rdparty/spirv-tools/source/opt/graphics_robust_access_pass.h
  15. 12 9
      3rdparty/spirv-tools/source/opt/optimizer.cpp
  16. 1 1
      3rdparty/spirv-tools/source/print.cpp
  17. 48 23
      3rdparty/spirv-tools/test/fuzz/equivalence_relation_test.cpp
  18. 116 69
      3rdparty/spirv-tools/test/fuzz/transformation_composite_construct_test.cpp
  19. 12 13
      3rdparty/spirv-tools/test/fuzz/transformation_composite_extract_test.cpp
  20. 28 20
      3rdparty/spirv-tools/test/fuzz/transformation_copy_object_test.cpp
  21. 9 2
      3rdparty/spirv-tools/test/fuzzers/spvtools_dis_fuzzer.cpp
  22. 4 4
      3rdparty/spirv-tools/test/opt/graphics_robust_access_test.cpp
  23. 1 1
      3rdparty/spirv-tools/utils/update_build_version.py
  24. 1 1
      3rdparty/spirv-tools/utils/vscode/package.json

+ 26 - 1
3rdparty/spirv-tools/BUILD.gn

@@ -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
3rdparty/spirv-tools/include/generated/build-version.inc

@@ -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"

+ 18 - 3
3rdparty/spirv-tools/source/fuzz/data_descriptor.cpp

@@ -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

+ 5 - 2
3rdparty/spirv-tools/source/fuzz/data_descriptor.h

@@ -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
 

+ 30 - 13
3rdparty/spirv-tools/source/fuzz/equivalence_relation.h

@@ -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_;
 };
 

+ 26 - 13
3rdparty/spirv-tools/source/fuzz/fact_manager.cpp

@@ -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

+ 16 - 11
3rdparty/spirv-tools/source/fuzz/fact_manager.h

@@ -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.
 };

+ 0 - 4
3rdparty/spirv-tools/source/fuzz/protobufs/spvtoolsfuzz.proto

@@ -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 {

+ 30 - 30
3rdparty/spirv-tools/source/fuzz/transformation_composite_construct.cpp

@@ -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(

+ 3 - 3
3rdparty/spirv-tools/source/fuzz/transformation_composite_extract.cpp

@@ -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 {

+ 3 - 3
3rdparty/spirv-tools/source/fuzz/transformation_copy_object.cpp

@@ -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 {

+ 3 - 2
3rdparty/spirv-tools/source/fuzz/transformation_replace_id_with_synonym.cpp

@@ -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;
   }
 

+ 0 - 1
3rdparty/spirv-tools/source/opt/graphics_robust_access_pass.cpp

@@ -160,7 +160,6 @@
 namespace spvtools {
 namespace opt {
 
-using opt::BasicBlock;
 using opt::Instruction;
 using opt::Operand;
 using spvtools::MakeUnique;

+ 4 - 3
3rdparty/spirv-tools/source/opt/graphics_robust_access_pass.h

@@ -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) {

+ 12 - 9
3rdparty/spirv-tools/source/opt/optimizer.cpp

@@ -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;
 }
 

+ 1 - 1
3rdparty/spirv-tools/source/print.cpp

@@ -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"; }

+ 48 - 23
3rdparty/spirv-tools/test/fuzz/equivalence_relation_test.cpp

@@ -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

+ 116 - 69
3rdparty/spirv-tools/test/fuzz/transformation_composite_construct_test.cpp

@@ -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

+ 12 - 13
3rdparty/spirv-tools/test/fuzz/transformation_composite_extract_test.cpp

@@ -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

+ 28 - 20
3rdparty/spirv-tools/test/fuzz/transformation_copy_object_test.cpp

@@ -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"(

+ 9 - 2
3rdparty/spirv-tools/test/fuzzers/spvtools_dis_fuzzer.cpp

@@ -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);

+ 4 - 4
3rdparty/spirv-tools/test/opt/graphics_robust_access_test.cpp

@@ -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";
 }
 

+ 1 - 1
3rdparty/spirv-tools/utils/update_build_version.py

@@ -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()

+ 1 - 1
3rdparty/spirv-tools/utils/vscode/package.json

@@ -18,7 +18,7 @@
                 "id": "spirv",
                 "configuration": "spirv.configuration.json",
                 "extensions": [
-                    "spirv"
+                    "spvasm"
                 ]
             }
         ],