From ad90ee2ec378184936fe1e5d868f32e048c22f12 Mon Sep 17 00:00:00 2001 From: David Neto Date: Mon, 23 Mar 2020 16:45:57 +0000 Subject: [PATCH] Add reader::spirv:SuggestSanitizedMemberName Also reader::spirv::GetMemberName Bug: tint:3 Change-Id: I4cf2dce0703eb17a9d49452294ed0c28ea158a07 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/17423 Reviewed-by: dan sinclair --- src/reader/spirv/namer.cc | 28 +++++++++++++++++++++++ src/reader/spirv/namer.h | 30 +++++++++++++++++++++++-- src/reader/spirv/namer_test.cc | 41 ++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 2 deletions(-) diff --git a/src/reader/spirv/namer.cc b/src/reader/spirv/namer.cc index d2353b43b2..4353291671 100644 --- a/src/reader/spirv/namer.cc +++ b/src/reader/spirv/namer.cc @@ -49,6 +49,19 @@ std::string Namer::Sanitize(const std::string& suggested_name) { return result; } +std::string Namer::GetMemberName(uint32_t struct_id, + uint32_t member_index) const { + std::string result; + auto where = struct_member_names_.find(struct_id); + if (where != struct_member_names_.end()) { + auto& member_names = where->second; + if (member_index < member_names.size()) { + result = member_names[member_index]; + } + } + return result; +} + std::string Namer::FindUnusedDerivedName(const std::string& base_name) const { // Ensure uniqueness among names. std::string derived_name; @@ -85,6 +98,21 @@ bool Namer::SuggestSanitizedName(uint32_t id, return SaveName(id, FindUnusedDerivedName(Sanitize(suggested_name))); } +bool Namer::SuggestSanitizedMemberName(uint32_t struct_id, + uint32_t member_index, + const std::string& suggested_name) { + // Creates an empty vector the first time we visit this struct. + auto& name_vector = struct_member_names_[struct_id]; + // Resizing will set new entries to the empty string. + name_vector.resize(std::max(name_vector.size(), size_t(member_index + 1))); + auto& entry = name_vector[member_index]; + if (entry.empty()) { + entry = Sanitize(suggested_name); + return true; + } + return false; +} + } // namespace spirv } // namespace reader } // namespace tint diff --git a/src/reader/spirv/namer.h b/src/reader/spirv/namer.h index 3c9d455aaa..d288216af3 100644 --- a/src/reader/spirv/namer.h +++ b/src/reader/spirv/namer.h @@ -18,6 +18,7 @@ #include #include #include +#include #include "src/reader/spirv/fail_stream.h" @@ -59,10 +60,19 @@ class Namer { /// @param id the SPIR-V ID /// @returns the name for the ID. It must have been registered. - const std::string& GetName(uint32_t id) { + const std::string& GetName(uint32_t id) const { return id_to_name_.find(id)->second; } + /// Gets the registered name for a struct member. If no name has + /// been registered for this member, then returns the empty string. + /// member index is in bounds. + /// @param id the SPIR-V ID of the struct + /// @param member_index the index of the member, counting from 0 + /// @returns the registered name for the ID, or an empty string if + /// nothing has been registered. + std::string GetMemberName(uint32_t id, uint32_t member_index) const; + /// Returns an unregistered name based on a given base name. /// @param base_name the base name /// @returns a new name @@ -76,12 +86,23 @@ class Namer { bool SaveName(uint32_t id, const std::string& name); /// Saves a sanitized name for the given ID, if that ID does not yet - /// have a registered name. + /// have a registered name, and if the sanitized name has not already + /// been registered to a different ID. /// @param id the SPIR-V ID /// @param suggested_name the suggested name /// @returns true if a name was newly registered for the ID bool SuggestSanitizedName(uint32_t id, const std::string& suggested_name); + /// Saves a sanitized name for a member of a struct, if that member + /// does not yet have a registered name. + /// @param id the SPIR-V ID for the struct + /// @param member_index the index of the member inside the struct + /// @param suggested_name the suggested name + /// @returns true if a name was newly registered + bool SuggestSanitizedMemberName(uint32_t id, + uint32_t member_index, + const std::string& suggested_name); + private: FailStream fail_stream_; @@ -89,6 +110,11 @@ class Namer { std::unordered_map id_to_name_; // Maps a name to a SPIR-V ID, or 0 (the case for derived names). std::unordered_map name_to_id_; + + // Maps a struct id and member index to a suggested sanitized name. + // If entry k in the vector is an empty string, then a suggestion + // was recorded for a higher-numbered index, but not for index k. + std::unordered_map> struct_member_names_; }; } // namespace spirv diff --git a/src/reader/spirv/namer_test.cc b/src/reader/spirv/namer_test.cc index e744a9d843..764863d179 100644 --- a/src/reader/spirv/namer_test.cc +++ b/src/reader/spirv/namer_test.cc @@ -175,6 +175,47 @@ TEST_F(SpvNamerTest, EXPECT_THAT(namer.GetName(9), Eq("rice_1")); } +TEST_F(SpvNamerTest, GetMemberName_EmptyStringForUnvisitedStruct) { + Namer namer(fail_stream_); + EXPECT_THAT(namer.GetMemberName(1, 2), Eq("")); +} + +TEST_F(SpvNamerTest, GetMemberName_EmptyStringForUnvisitedMember) { + Namer namer(fail_stream_); + namer.SuggestSanitizedMemberName(1, 2, "mother"); + EXPECT_THAT(namer.GetMemberName(1, 0), Eq("")); +} + +TEST_F(SpvNamerTest, SuggestSanitizedMemberName_TakeSuggestionWhenNoConflict) { + Namer namer(fail_stream_); + EXPECT_TRUE(namer.SuggestSanitizedMemberName(1, 2, "mother")); + EXPECT_THAT(namer.GetMemberName(1, 2), Eq("mother")); +} + +TEST_F(SpvNamerTest, SuggestSanitizedMemberName_TakeSanitizedSuggestion) { + Namer namer(fail_stream_); + EXPECT_TRUE(namer.SuggestSanitizedMemberName(1, 2, "m:t%er")); + EXPECT_THAT(namer.GetMemberName(1, 2), Eq("m_t_er")); +} + +TEST_F( + SpvNamerTest, + SuggestSanitizedMemberName_TakeSuggestionWhenNoConflictAfterSuggestionForLowerMember) { + Namer namer(fail_stream_); + EXPECT_TRUE(namer.SuggestSanitizedMemberName(1, 7, "mother")); + EXPECT_THAT(namer.GetMemberName(1, 2), Eq("")); + EXPECT_TRUE(namer.SuggestSanitizedMemberName(1, 2, "mary")); + EXPECT_THAT(namer.GetMemberName(1, 2), Eq("mary")); +} + +TEST_F(SpvNamerTest, + SuggestSanitizedMemberName_RejectSuggestionIfConflictOnMember) { + Namer namer(fail_stream_); + EXPECT_TRUE(namer.SuggestSanitizedMemberName(1, 2, "mother")); + EXPECT_FALSE(namer.SuggestSanitizedMemberName(1, 2, "mary")); + EXPECT_THAT(namer.GetMemberName(1, 2), Eq("mother")); +} + } // namespace } // namespace spirv } // namespace reader