blob: 9277136643a712b4b23574744f9a4654d8f55642 [file] [log] [blame]
// 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 <memory>
#include <unordered_set>
#include <utility>
#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, const DataMap&) {
ProgramBuilder out;
CloneContext ctx(&out, in);
// Swizzles and intrinsic calls need to keep their symbols preserved.
std::unordered_set<ast::IdentifierExpression*> preserve;
for (auto* node : in->ASTNodes().Objects()) {
if (auto* member = node->As<ast::MemberAccessorExpression>()) {
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<ast::CallExpression>()) {
auto* sem = in->Sem().Get(call);
if (!sem) {
TINT_ICE(out.Diagnostics()) << "CallExpression has no semantic info";
continue;
}
if (sem->Target()->Is<semantic::Intrinsic>()) {
preserve.emplace(call->func()->As<ast::IdentifierExpression>());
}
}
}
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<ast::IdentifierExpression>(
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<Data>(std::move(remappings)));
}
} // namespace transform
} // namespace tint