// 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/transform/transform.h" #include #include #include "src/program_builder.h" #include "src/sem/atomic_type.h" #include "src/sem/block_statement.h" #include "src/sem/depth_multisampled_texture_type.h" #include "src/sem/for_loop_statement.h" #include "src/sem/reference_type.h" #include "src/sem/sampler_type.h" TINT_INSTANTIATE_TYPEINFO(tint::transform::Transform); TINT_INSTANTIATE_TYPEINFO(tint::transform::Data); namespace tint { namespace transform { Data::Data() = default; Data::Data(const Data&) = default; Data::~Data() = default; Data& Data::operator=(const Data&) = default; DataMap::DataMap() = default; DataMap::DataMap(DataMap&&) = default; DataMap::~DataMap() = default; DataMap& DataMap::operator=(DataMap&&) = default; Output::Output() = default; Output::Output(Program&& p) : program(std::move(p)) {} Transform::Transform() = default; Transform::~Transform() = default; Output Transform::Run(const Program* program, const DataMap& data /* = {} */) { ProgramBuilder builder; CloneContext ctx(&builder, program); Output output; Run(ctx, data, output.data); builder.SetTransformApplied(this); output.program = Program(std::move(builder)); return output; } void Transform::Run(CloneContext& ctx, const DataMap&, DataMap&) { TINT_UNIMPLEMENTED(Transform, ctx.dst->Diagnostics()) << "Transform::Run() unimplemented for " << TypeInfo().name; } bool Transform::Requires(CloneContext& ctx, std::initializer_list deps) { for (auto* dep : deps) { if (!ctx.src->HasTransformApplied(dep)) { ctx.dst->Diagnostics().add_error( diag::System::Transform, std::string(TypeInfo().name) + " depends on " + std::string(dep->name) + " but the dependency was not run"); return false; } } return true; } ast::DecorationList Transform::RemoveDecorations( CloneContext& ctx, const ast::DecorationList& in, std::function should_remove) { ast::DecorationList new_decorations; for (auto* deco : in) { if (!should_remove(deco)) { new_decorations.push_back(ctx.Clone(deco)); } } return new_decorations; } void Transform::RemoveStatement(CloneContext& ctx, ast::Statement* stmt) { auto* sem = ctx.src->Sem().Get(stmt); if (auto* block = tint::As(sem->Parent())) { ctx.Remove(block->Declaration()->statements(), stmt); return; } if (tint::Is(sem->Parent())) { ctx.Replace(stmt, static_cast(nullptr)); return; } TINT_ICE(Transform, ctx.dst->Diagnostics()) << "unable to remove statement from parent of type " << sem->TypeInfo().name; } ast::Type* Transform::CreateASTTypeFor(CloneContext& ctx, const sem::Type* ty) { if (ty->Is()) { return ctx.dst->create(); } if (ty->Is()) { return ctx.dst->create(); } if (ty->Is()) { return ctx.dst->create(); } if (ty->Is()) { return ctx.dst->create(); } if (ty->Is()) { return ctx.dst->create(); } if (auto* m = ty->As()) { auto* el = CreateASTTypeFor(ctx, m->type()); return ctx.dst->create(el, m->rows(), m->columns()); } if (auto* v = ty->As()) { auto* el = CreateASTTypeFor(ctx, v->type()); return ctx.dst->create(el, v->Width()); } if (auto* a = ty->As()) { auto* el = CreateASTTypeFor(ctx, a->ElemType()); ast::DecorationList decos; if (!a->IsStrideImplicit()) { decos.emplace_back(ctx.dst->create(a->Stride())); } return ctx.dst->create(el, a->Count(), std::move(decos)); } if (auto* s = ty->As()) { return ctx.dst->create(ctx.Clone(s->Declaration()->name())); } if (auto* s = ty->As()) { return CreateASTTypeFor(ctx, s->StoreType()); } if (auto* a = ty->As()) { return ctx.dst->create(CreateASTTypeFor(ctx, a->Type())); } if (auto* t = ty->As()) { return ctx.dst->create(t->dim()); } if (auto* t = ty->As()) { return ctx.dst->create(t->dim()); } if (auto* t = ty->As()) { return ctx.dst->create( t->dim(), CreateASTTypeFor(ctx, t->type())); } if (auto* t = ty->As()) { return ctx.dst->create( t->dim(), CreateASTTypeFor(ctx, t->type())); } if (auto* t = ty->As()) { return ctx.dst->create( t->dim(), t->image_format(), CreateASTTypeFor(ctx, t->type()), t->access()); } if (auto* s = ty->As()) { return ctx.dst->create(s->kind()); } TINT_UNREACHABLE(Transform, ctx.dst->Diagnostics()) << "Unhandled type: " << ty->TypeInfo().name; return nullptr; } } // namespace transform } // namespace tint