blob: 8cc1f9c95371c22b1730ff7b6078800bf5e66abb [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/binding_remapper.h"
#include <utility>
#include "src/program_builder.h"
#include "src/semantic/variable.h"
#include "src/type/access_control_type.h"
TINT_INSTANTIATE_TYPEINFO(tint::transform::BindingRemapper::Remappings);
namespace tint {
namespace transform {
BindingRemapper::Remappings::Remappings(BindingPoints bp, AccessControls ac)
: binding_points(std::move(bp)), access_controls(std::move(ac)) {}
BindingRemapper::Remappings::Remappings(const Remappings&) = default;
BindingRemapper::Remappings::~Remappings() = default;
BindingRemapper::BindingRemapper() = default;
BindingRemapper::~BindingRemapper() = default;
Output BindingRemapper::Run(const Program* in, const DataMap& datamap) {
ProgramBuilder out;
auto* remappings = datamap.Get<Remappings>();
if (!remappings) {
out.Diagnostics().add_error(
"BindingRemapper did not find the remapping data");
return Output(Program(std::move(out)));
}
CloneContext ctx(&out, in);
for (auto* var : in->AST().GlobalVariables()) {
if (auto binding_point = var->binding_point()) {
BindingPoint from{binding_point.group->value(),
binding_point.binding->value()};
// Replace any group or binding decorations.
// Note: This has to be performed *before* remapping access controls, as
// `ctx.Clone(var->decorations())` depend on these replacements.
auto bp_it = remappings->binding_points.find(from);
if (bp_it != remappings->binding_points.end()) {
BindingPoint to = bp_it->second;
auto* new_group = out.create<ast::GroupDecoration>(to.group);
auto* new_binding = out.create<ast::BindingDecoration>(to.binding);
ctx.Replace(binding_point.group, new_group);
ctx.Replace(binding_point.binding, new_binding);
}
// Replace any access controls.
auto ac_it = remappings->access_controls.find(from);
if (ac_it != remappings->access_controls.end()) {
ast::AccessControl ac = ac_it->second;
auto* ty = in->Sem().Get(var)->Type();
type::Type* inner_ty = nullptr;
if (auto* old_ac = ty->As<type::AccessControl>()) {
inner_ty = ctx.Clone(old_ac->type());
} else {
inner_ty = ctx.Clone(ty);
}
auto* new_ty = ctx.dst->create<type::AccessControl>(ac, inner_ty);
auto* new_var = ctx.dst->create<ast::Variable>(
ctx.Clone(var->source()), ctx.Clone(var->symbol()),
var->declared_storage_class(), new_ty, var->is_const(),
ctx.Clone(var->constructor()), ctx.Clone(var->decorations()));
ctx.Replace(var, new_var);
}
}
}
ctx.Clone();
return Output(Program(std::move(out)));
}
} // namespace transform
} // namespace tint