diff --git a/BUILD.gn b/BUILD.gn index 80d4a4fdd8..f4361e041c 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -455,6 +455,7 @@ source_set("libtint_core_src") { "src/type/void_type.h", "src/type_determiner.cc", "src/type_determiner.h", + "src/utils/unique_vector.h", "src/validator/validator.cc", "src/validator/validator.h", "src/validator/validator_impl.cc", @@ -868,6 +869,7 @@ source_set("tint_unittests_core_src") { "src/type/u32_type_test.cc", "src/type/vector_type_test.cc", "src/type_determiner_test.cc", + "src/utils/unique_vector_test.cc", "src/validator/validator_builtins_test.cc", "src/validator/validator_control_block_test.cc", "src/validator/validator_function_test.cc", diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 008ce14002..2a9376c12d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -269,6 +269,7 @@ set(TINT_LIB_SRCS type/vector_type.h type/void_type.cc type/void_type.h + utils/unique_vector.h validator/validator.cc validator/validator.h validator/validator_impl.cc @@ -492,6 +493,7 @@ if(${TINT_BUILD_TESTS}) type/type_manager_test.cc type/u32_type_test.cc type/vector_type_test.cc + utils/unique_vector_test.cc validator/validator_builtins_test.cc validator/validator_control_block_test.cc validator/validator_function_test.cc diff --git a/src/type_determiner.cc b/src/type_determiner.cc index a72c3ab411..3e0a7973cc 100644 --- a/src/type_determiner.cc +++ b/src/type_determiner.cc @@ -125,9 +125,9 @@ void TypeDeterminer::set_referenced_from_function_if_needed(VariableInfo* var, return; } - current_function_->referenced_module_vars.Add(var); + current_function_->referenced_module_vars.add(var); if (local) { - current_function_->local_referenced_module_vars.Add(var); + current_function_->local_referenced_module_vars.add(var); } } @@ -172,7 +172,7 @@ bool TypeDeterminer::DetermineInternal() { void TypeDeterminer::set_entry_points(const Symbol& fn_sym, Symbol ep_sym) { auto* info = symbol_to_function_.at(fn_sym); - info->ancestor_entry_points.Add(ep_sym); + info->ancestor_entry_points.add(ep_sym); for (const auto& callee : caller_to_callee_[fn_sym]) { set_entry_points(callee, ep_sym); diff --git a/src/type_determiner.h b/src/type_determiner.h index b03b1d5e56..f661c27a8c 100644 --- a/src/type_determiner.h +++ b/src/type_determiner.h @@ -28,6 +28,7 @@ #include "src/scope_stack.h" #include "src/semantic/intrinsic.h" #include "src/type/storage_texture_type.h" +#include "src/utils/unique_vector.h" namespace tint { @@ -78,26 +79,6 @@ class TypeDeterminer { static semantic::IntrinsicType MatchIntrinsicType(const std::string& name); private: - template - struct UniqueVector { - using ConstIterator = typename std::vector::const_iterator; - - void Add(const T& val) { - if (set.count(val) == 0) { - vector.emplace_back(val); - set.emplace(val); - } - } - size_t size() const { return vector.size(); } - ConstIterator begin() const { return vector.begin(); } - ConstIterator end() const { return vector.end(); } - operator const std::vector &() const { return vector; } - - private: - std::vector vector; - std::unordered_set set; - }; - /// Structure holding semantic information about a variable. /// Used to build the semantic::Variable nodes at the end of resolving. struct VariableInfo { diff --git a/src/utils/unique_vector.h b/src/utils/unique_vector.h new file mode 100644 index 0000000000..36016eec0e --- /dev/null +++ b/src/utils/unique_vector.h @@ -0,0 +1,59 @@ +// Copyright 2021 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_UTILS_UNIQUE_VECTOR_H_ +#define SRC_UTILS_UNIQUE_VECTOR_H_ + +#include +#include + +namespace tint { + +/// UniqueVector is an ordered container that only contains unique items. +/// Attempting to add a duplicate is a no-op. +template +struct UniqueVector { + /// The iterator returned by begin() and end() + using ConstIterator = typename std::vector::const_iterator; + + /// add appends the item to the end of the vector, if the vector does not + /// already contain the given item. + /// @param item the item to append to the end of the vector + void add(const T& item) { + if (set.count(item) == 0) { + vector.emplace_back(item); + set.emplace(item); + } + } + + /// @returns the number of items in the vector + size_t size() const { return vector.size(); } + + /// @returns an iterator to the beginning of the vector + ConstIterator begin() const { return vector.begin(); } + + /// @returns an iterator to the end of the vector + ConstIterator end() const { return vector.end(); } + + /// @returns a const reference to the internal vector + operator const std::vector &() const { return vector; } + + private: + std::vector vector; + std::unordered_set set; +}; + +} // namespace tint + +#endif // SRC_UTILS_UNIQUE_VECTOR_H_ diff --git a/src/utils/unique_vector_test.cc b/src/utils/unique_vector_test.cc new file mode 100644 index 0000000000..83f19e5992 --- /dev/null +++ b/src/utils/unique_vector_test.cc @@ -0,0 +1,76 @@ +// Copyright 2021 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/utils/unique_vector.h" + +#include "gtest/gtest.h" + +namespace tint { +namespace { + +TEST(UniqueVectorTest, Empty) { + UniqueVector unique_vec; + EXPECT_EQ(unique_vec.size(), 0u); + EXPECT_EQ(unique_vec.begin(), unique_vec.end()); +} + +TEST(UniqueVectorTest, AddUnique) { + UniqueVector unique_vec; + unique_vec.add(0); + unique_vec.add(1); + unique_vec.add(2); + EXPECT_EQ(unique_vec.size(), 3u); + int i = 0; + for (auto n : unique_vec) { + EXPECT_EQ(n, i); + i++; + } +} + +TEST(UniqueVectorTest, AddDuplicates) { + UniqueVector unique_vec; + unique_vec.add(0); + unique_vec.add(0); + unique_vec.add(0); + unique_vec.add(1); + unique_vec.add(1); + unique_vec.add(2); + EXPECT_EQ(unique_vec.size(), 3u); + int i = 0; + for (auto n : unique_vec) { + EXPECT_EQ(n, i); + i++; + } +} + +TEST(UniqueVectorTest, AsVector) { + UniqueVector unique_vec; + unique_vec.add(0); + unique_vec.add(0); + unique_vec.add(0); + unique_vec.add(1); + unique_vec.add(1); + unique_vec.add(2); + + const std::vector& vec = unique_vec; + EXPECT_EQ(vec.size(), 3u); + int i = 0; + for (auto n : vec) { + EXPECT_EQ(n, i); + i++; + } +} + +} // namespace +} // namespace tint