diff --git a/BUILD.gn b/BUILD.gn index fdc52e82a4..bda10ba1f1 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -411,6 +411,8 @@ source_set("libtint_core_src") { "src/transform/first_index_offset.h", "src/transform/manager.cc", "src/transform/manager.h", + "src/transform/renamer.cc", + "src/transform/renamer.h", "src/transform/transform.cc", "src/transform/transform.h", "src/transform/vertex_pulling.cc", @@ -852,6 +854,7 @@ source_set("tint_unittests_core_src") { "src/transform/bound_array_accessors_test.cc", "src/transform/emit_vertex_point_size_test.cc", "src/transform/first_index_offset_test.cc", + "src/transform/renamer_test.cc", "src/transform/test_helper.h", "src/transform/vertex_pulling_test.cc", "src/type/access_control_type_test.cc", diff --git a/include/tint/tint.h b/include/tint/tint.h index e8b37109e6..54656c8d78 100644 --- a/include/tint/tint.h +++ b/include/tint/tint.h @@ -28,6 +28,7 @@ #include "src/transform/emit_vertex_point_size.h" #include "src/transform/first_index_offset.h" #include "src/transform/manager.h" +#include "src/transform/renamer.h" #include "src/transform/vertex_pulling.h" #include "src/type/type_manager.h" #include "src/validator/validator.h" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cc188ecdbf..3453117f0e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -225,6 +225,8 @@ set(TINT_LIB_SRCS transform/first_index_offset.h transform/manager.cc transform/manager.h + transform/renamer.cc + transform/renamer.h transform/transform.cc transform/transform.h transform/vertex_pulling.cc @@ -711,6 +713,7 @@ if(${TINT_BUILD_TESTS}) transform/bound_array_accessors_test.cc transform/emit_vertex_point_size_test.cc transform/first_index_offset_test.cc + transform/renamer_test.cc transform/test_helper.h transform/vertex_pulling_test.cc ) diff --git a/src/transform/renamer.cc b/src/transform/renamer.cc new file mode 100644 index 0000000000..3527f4dee9 --- /dev/null +++ b/src/transform/renamer.cc @@ -0,0 +1,62 @@ +// 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/transform/renamer.h" + +#include +#include + +#include "src/program_builder.h" + +TINT_INSTANTIATE_TYPEINFO(tint::transform::Renamer::Data); + +namespace tint { +namespace transform { + +Renamer::Data::Data(Remappings&& r) : remappings(std::move(r)) {} + +Renamer::Data::Data(const Data&) = default; + +Renamer::Data::~Data() = default; + +Renamer::Renamer() : cfg_{} {} + +Renamer::Renamer(const Config& config) : cfg_(config) {} + +Renamer::~Renamer() = default; + +Transform::Output Renamer::Run(const Program* in) { + ProgramBuilder out; + CloneContext ctx(&out, in); + + Data::Remappings remappings; + + switch (cfg_.method) { + case Method::kMonotonic: + ctx.ReplaceAll([&](Symbol sym) { + auto str_in = in->Symbols().NameFor(sym); + auto str_out = "_tint_" + std::to_string(sym.value()); + remappings.emplace(str_in, str_out); + return out.Symbols().Register(str_out); + }); + break; + } + ctx.Clone(); + + return Output(Program(std::move(out)), + std::make_unique(std::move(remappings))); +} + +} // namespace transform +} // namespace tint diff --git a/src/transform/renamer.h b/src/transform/renamer.h new file mode 100644 index 0000000000..2b5e21975b --- /dev/null +++ b/src/transform/renamer.h @@ -0,0 +1,83 @@ +// 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_TRANSFORM_RENAMER_H_ +#define SRC_TRANSFORM_RENAMER_H_ + +#include +#include + +#include "src/transform/transform.h" + +namespace tint { +namespace transform { + +/// Renamer is a Transform that renames all the symbols in a program. +class Renamer : public Transform { + public: + /// Data holds information about shader usage and constant buffer offsets. + struct Data : public Castable { + /// Remappings is a map of old symbol name to new symbol name + using Remappings = std::unordered_map; + + /// Constructor + /// @param remappings the symbol remappings + explicit Data(Remappings&& remappings); + + /// Copy constructor + Data(const Data&); + + /// Destructor + ~Data() override; + + /// A map of old symbol name to new symbol name + Remappings const remappings; + }; + + /// Method is an enumerator of renaming methods that can be used + enum class Method { + /// Every symbol will be replaced with an identifier containing a + /// monotonically incrementing integer. + kMonotonic, + }; + + /// Configuration options for the transform + struct Config { + /// The method used for renaming symbols + Method method = Method::kMonotonic; + }; + + /// Constructor using a default configuration + Renamer(); + + /// Constructor + /// @param config the configuration for the transform + explicit Renamer(const Config& config); + + /// Destructor + ~Renamer() override; + + /// Runs the transform on `program`, returning the transformation result. + /// @param program the source program to transform + /// @returns the transformation result + Output Run(const Program* program) override; + + private: + Config const cfg_; +}; + +} // namespace transform +} // namespace tint + +#endif // SRC_TRANSFORM_RENAMER_H_ diff --git a/src/transform/renamer_test.cc b/src/transform/renamer_test.cc new file mode 100644 index 0000000000..63d68c36a4 --- /dev/null +++ b/src/transform/renamer_test.cc @@ -0,0 +1,85 @@ +// 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/transform/renamer.h" + +#include "gmock/gmock.h" +#include "src/transform/test_helper.h" + +namespace tint { +namespace transform { +namespace { + +using ::testing::ContainerEq; + +using RenamerTest = TransformTest; + +TEST_F(RenamerTest, EmptyModule) { + auto* src = ""; + auto* expect = ""; + + auto got = Transform(src); + + EXPECT_EQ(expect, str(got)); + + auto* data = got.data.Get(); + + ASSERT_EQ(data->remappings.size(), 0u); +} + +TEST_F(RenamerTest, BasicModuleVertexIndex) { + auto* src = R"( +[[builtin(vertex_index)]] var vert_idx : u32; + +fn test() -> u32 { + return vert_idx; +} + +[[stage(vertex)]] +fn entry() -> void { + test(); +} +)"; + + auto* expect = R"( +[[builtin(vertex_index)]] var _tint_1 : u32; + +fn _tint_2() -> u32 { + return _tint_1; +} + +[[stage(vertex)]] +fn _tint_3() -> void { + _tint_2(); +} +)"; + + auto got = Transform(src); + + EXPECT_EQ(expect, str(got)); + + auto* data = got.data.Get(); + + ASSERT_NE(data, nullptr); + Renamer::Data::Remappings expected_remappings = { + {"vert_idx", "_tint_1"}, + {"test", "_tint_2"}, + {"entry", "_tint_3"}, + }; + EXPECT_THAT(data->remappings, ContainerEq(expected_remappings)); +} + +} // namespace +} // namespace transform +} // namespace tint