Add reader::spirv::Namer

A Namer is a place for saving and looking up names
based on SPIR-V IDs.

Bug: tint:3
Change-Id: I6aeb2f5f7ba63c2e0a816dcbac88f964beafabc6
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/17284
Reviewed-by: dan sinclair <dsinclair@google.com>
This commit is contained in:
David Neto 2020-03-20 19:24:23 +00:00 committed by dan sinclair
parent 3740fd2d46
commit be4c89a4d2
4 changed files with 217 additions and 0 deletions

View File

@ -199,6 +199,8 @@ set(TINT_LIB_SRCS
if(${TINT_BUILD_SPV_READER})
list(APPEND TINT_LIB_SRCS
reader/spirv/fail_stream.h
reader/spirv/namer.cc
reader/spirv/namer.h
reader/spirv/parser.cc
reader/spirv/parser.h
reader/spirv/parser_impl.cc
@ -313,6 +315,7 @@ endif()
if(${TINT_BUILD_SPV_READER})
list(APPEND TINT_TEST_SRCS
reader/spirv/fail_stream_test.cc
reader/spirv/namer_test.cc
reader/spirv/parser_impl_import_test.cc
reader/spirv/parser_impl_test.cc
reader/spirv/parser_test.cc

36
src/reader/spirv/namer.cc Normal file
View File

@ -0,0 +1,36 @@
// Copyright 2020 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/reader/spirv/namer.h"
namespace tint {
namespace reader {
namespace spirv {
Namer::Namer(const FailStream& fail_stream) : fail_stream_(fail_stream) {}
Namer::~Namer() = default;
bool Namer::SaveName(uint32_t id, const std::string& name) {
if (HasName(id)) {
return Fail() << "internal error: ID " << id
<< " already has registered name: " << id_to_name_[id];
}
id_to_name_[id] = name;
return true;
}
} // namespace spirv
} // namespace reader
} // namespace tint

71
src/reader/spirv/namer.h Normal file
View File

@ -0,0 +1,71 @@
// Copyright 2020 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_READER_SPIRV_NAMER_H_
#define SRC_READER_SPIRV_NAMER_H_
#include <cstdint>
#include <string>
#include <unordered_map>
#include "src/reader/spirv/fail_stream.h"
namespace tint {
namespace reader {
namespace spirv {
/// A Namer maps SPIR-V IDs to strings.
class Namer {
public:
/// Creates a new namer
/// @param fail_stream the error reporting stream
explicit Namer(const FailStream& fail_stream);
/// Destructor
~Namer();
/// Registers a failure.
/// @returns a fail stream to accumulate diagnostics.
FailStream& Fail() { return fail_stream_.Fail(); }
/// @param id the SPIR-V ID
/// @returns true if we the given ID already has a registered name.
bool HasName(uint32_t id) {
return id_to_name_.find(id) != id_to_name_.end();
}
/// @param id the SPIR-V ID
/// @returns the name for the ID. It must have been registered.
const std::string& GetName(uint32_t id) {
return id_to_name_.find(id)->second;
}
/// Records a mapping from the given ID to a name. Emits a failure
/// if the ID already has a registered name.
/// @param id the SPIR-V ID
/// @param name the name to map to the ID
/// @returns true if the ID did not have a previously registered name.
bool SaveName(uint32_t id, const std::string& name);
private:
FailStream fail_stream_;
// Maps an ID to its registered name.
std::unordered_map<uint32_t, std::string> id_to_name_;
};
} // namespace spirv
} // namespace reader
} // namespace tint
#endif // SRC_READER_SPIRV_NAMER_H_

View File

@ -0,0 +1,107 @@
// Copyright 2020 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/reader/spirv/namer.h"
#include <cstdint>
#include <sstream>
#include <string>
#include "gtest/gtest.h"
#include "src/reader/spirv/fail_stream.h"
namespace tint {
namespace reader {
namespace spirv {
namespace {
class SpvNamerTest : public testing::Test {
public:
SpvNamerTest() : fail_stream_(&success_, &errors_) {}
/// @returns the accumulated diagnostic strings
std::string error() { return errors_.str(); }
protected:
std::stringstream errors_;
bool success_ = true;
FailStream fail_stream_;
};
TEST_F(SpvNamerTest, NoFailureToStart) {
Namer namer(fail_stream_);
EXPECT_TRUE(success_);
EXPECT_TRUE(error().empty());
}
TEST_F(SpvNamerTest, FailLogsError) {
Namer namer(fail_stream_);
const bool converted_result = namer.Fail() << "st. johns wood";
EXPECT_FALSE(converted_result);
EXPECT_EQ(error(), "st. johns wood");
EXPECT_FALSE(success_);
}
TEST_F(SpvNamerTest, NoNameRecorded) {
Namer namer(fail_stream_);
EXPECT_FALSE(namer.HasName(12));
EXPECT_TRUE(success_);
EXPECT_TRUE(error().empty());
}
TEST_F(SpvNamerTest, SaveNameOnce) {
Namer namer(fail_stream_);
const uint32_t id = 9;
EXPECT_FALSE(namer.HasName(id));
const bool save_result = namer.SaveName(id, "abbey road");
EXPECT_TRUE(save_result);
EXPECT_TRUE(namer.HasName(id));
EXPECT_EQ(namer.GetName(id), "abbey road");
EXPECT_TRUE(success_);
EXPECT_TRUE(error().empty());
}
TEST_F(SpvNamerTest, SaveNameTwoIds) {
Namer namer(fail_stream_);
EXPECT_FALSE(namer.HasName(8));
EXPECT_FALSE(namer.HasName(9));
EXPECT_TRUE(namer.SaveName(8, "abbey road"));
EXPECT_TRUE(namer.SaveName(9, "rubber soul"));
EXPECT_TRUE(namer.HasName(8));
EXPECT_TRUE(namer.HasName(9));
EXPECT_EQ(namer.GetName(9), "rubber soul");
EXPECT_EQ(namer.GetName(8), "abbey road");
EXPECT_TRUE(success_);
EXPECT_TRUE(error().empty());
}
TEST_F(SpvNamerTest, SaveNameFailsDueToIdReuse) {
Namer namer(fail_stream_);
const uint32_t id = 9;
EXPECT_TRUE(namer.SaveName(id, "abbey road"));
EXPECT_FALSE(namer.SaveName(id, "rubber soul"));
EXPECT_TRUE(namer.HasName(id));
EXPECT_EQ(namer.GetName(id), "abbey road");
EXPECT_FALSE(success_);
EXPECT_FALSE(error().empty());
}
} // namespace
} // namespace spirv
} // namespace reader
} // namespace tint