// 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 #include "src/program_builder.h" #include "src/semantic/call.h" #include "src/semantic/member_accessor_expression.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); // Swizzles and intrinsic calls need to keep their symbols preserved. std::unordered_set preserve; for (auto* node : in->ASTNodes().Objects()) { if (auto* member = node->As()) { auto* sem = in->Sem().Get(member); if (!sem) { TINT_ICE(out.Diagnostics()) << "MemberAccessorExpression has no semantic info"; continue; } if (sem->IsSwizzle()) { preserve.emplace(member->member()); } } else if (auto* call = node->As()) { auto* sem = in->Sem().Get(call); if (!sem) { TINT_ICE(out.Diagnostics()) << "CallExpression has no semantic info"; continue; } if (sem->Target()->Is()) { preserve.emplace(call->func()->As()); } } } Data::Remappings remappings; switch (cfg_.method) { case Method::kMonotonic: ctx.ReplaceAll([&](Symbol sym) { auto str_in = in->Symbols().NameFor(sym); auto it = remappings.find(str_in); if (it != remappings.end()) { return out.Symbols().Get(it->second); } auto str_out = "_tint_" + std::to_string(remappings.size() + 1); remappings.emplace(str_in, str_out); return out.Symbols().Register(str_out); }); ctx.ReplaceAll( [&](ast::IdentifierExpression* ident) -> ast::IdentifierExpression* { if (preserve.count(ident)) { auto sym_in = ident->symbol(); auto str = in->Symbols().NameFor(sym_in); auto sym_out = out.Symbols().Register(str); return ctx.dst->create( ctx.Clone(ident->source()), sym_out); } return nullptr; // Clone ident. Uses the symbol remapping above. }); break; } ctx.Clone(); return Output(Program(std::move(out)), std::make_unique(std::move(remappings))); } } // namespace transform } // namespace tint