1cb93a386Sopenharmony_ci// Copyright 2020 The Tint Authors. 2cb93a386Sopenharmony_ci// 3cb93a386Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4cb93a386Sopenharmony_ci// you may not use this file except in compliance with the License. 5cb93a386Sopenharmony_ci// You may obtain a copy of the License at 6cb93a386Sopenharmony_ci// 7cb93a386Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8cb93a386Sopenharmony_ci// 9cb93a386Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10cb93a386Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11cb93a386Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cb93a386Sopenharmony_ci// See the License for the specific language governing permissions and 13cb93a386Sopenharmony_ci// limitations under the License. 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#include "src/clone_context.h" 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ci#include <string> 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci#include "src/program_builder.h" 20cb93a386Sopenharmony_ci#include "src/utils/map.h" 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_ciTINT_INSTANTIATE_TYPEINFO(tint::Cloneable); 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_cinamespace tint { 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ciCloneContext::ListTransforms::ListTransforms() = default; 27cb93a386Sopenharmony_ciCloneContext::ListTransforms::~ListTransforms() = default; 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ciCloneContext::CloneContext(ProgramBuilder* to, 30cb93a386Sopenharmony_ci Program const* from, 31cb93a386Sopenharmony_ci bool auto_clone_symbols) 32cb93a386Sopenharmony_ci : dst(to), src(from) { 33cb93a386Sopenharmony_ci if (auto_clone_symbols) { 34cb93a386Sopenharmony_ci // Almost all transforms will want to clone all symbols before doing any 35cb93a386Sopenharmony_ci // work, to avoid any newly created symbols clashing with existing symbols 36cb93a386Sopenharmony_ci // in the source program and causing them to be renamed. 37cb93a386Sopenharmony_ci from->Symbols().Foreach([&](Symbol s, const std::string&) { Clone(s); }); 38cb93a386Sopenharmony_ci } 39cb93a386Sopenharmony_ci} 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ciCloneContext::CloneContext(ProgramBuilder* builder) 42cb93a386Sopenharmony_ci : CloneContext(builder, nullptr, false) {} 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ciCloneContext::~CloneContext() = default; 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ciSymbol CloneContext::Clone(Symbol s) { 47cb93a386Sopenharmony_ci if (!src) { 48cb93a386Sopenharmony_ci return s; // In-place clone 49cb93a386Sopenharmony_ci } 50cb93a386Sopenharmony_ci return utils::GetOrCreate(cloned_symbols_, s, [&]() -> Symbol { 51cb93a386Sopenharmony_ci if (symbol_transform_) { 52cb93a386Sopenharmony_ci return symbol_transform_(s); 53cb93a386Sopenharmony_ci } 54cb93a386Sopenharmony_ci return dst->Symbols().New(src->Symbols().NameFor(s)); 55cb93a386Sopenharmony_ci }); 56cb93a386Sopenharmony_ci} 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_civoid CloneContext::Clone() { 59cb93a386Sopenharmony_ci dst->AST().Copy(this, &src->AST()); 60cb93a386Sopenharmony_ci dst->SetTransformApplied(src->TransformsApplied()); 61cb93a386Sopenharmony_ci} 62cb93a386Sopenharmony_ci 63cb93a386Sopenharmony_ciast::FunctionList CloneContext::Clone(const ast::FunctionList& v) { 64cb93a386Sopenharmony_ci ast::FunctionList out; 65cb93a386Sopenharmony_ci out.reserve(v.size()); 66cb93a386Sopenharmony_ci for (const ast::Function* el : v) { 67cb93a386Sopenharmony_ci out.Add(Clone(el)); 68cb93a386Sopenharmony_ci } 69cb93a386Sopenharmony_ci return out; 70cb93a386Sopenharmony_ci} 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ciconst tint::Cloneable* CloneContext::CloneCloneable(const Cloneable* object) { 73cb93a386Sopenharmony_ci // If the input is nullptr, there's nothing to clone - just return nullptr. 74cb93a386Sopenharmony_ci if (object == nullptr) { 75cb93a386Sopenharmony_ci return nullptr; 76cb93a386Sopenharmony_ci } 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci // Was Replace() called for this object? 79cb93a386Sopenharmony_ci auto it = replacements_.find(object); 80cb93a386Sopenharmony_ci if (it != replacements_.end()) { 81cb93a386Sopenharmony_ci return it->second(); 82cb93a386Sopenharmony_ci } 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci // Attempt to clone using the registered replacer functions. 85cb93a386Sopenharmony_ci auto& typeinfo = object->TypeInfo(); 86cb93a386Sopenharmony_ci for (auto& transform : transforms_) { 87cb93a386Sopenharmony_ci if (typeinfo.Is(*transform.typeinfo)) { 88cb93a386Sopenharmony_ci if (auto* transformed = transform.function(object)) { 89cb93a386Sopenharmony_ci return transformed; 90cb93a386Sopenharmony_ci } 91cb93a386Sopenharmony_ci break; 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci // No transform for this type, or the transform returned nullptr. 96cb93a386Sopenharmony_ci // Clone with T::Clone(). 97cb93a386Sopenharmony_ci return object->Clone(this); 98cb93a386Sopenharmony_ci} 99cb93a386Sopenharmony_ci 100cb93a386Sopenharmony_civoid CloneContext::CheckedCastFailure(const Cloneable* got, 101cb93a386Sopenharmony_ci const TypeInfo& expected) { 102cb93a386Sopenharmony_ci TINT_ICE(Clone, Diagnostics()) 103cb93a386Sopenharmony_ci << "Cloned object was not of the expected type\n" 104cb93a386Sopenharmony_ci << "got: " << got->TypeInfo().name << "\n" 105cb93a386Sopenharmony_ci << "expected: " << expected.name; 106cb93a386Sopenharmony_ci} 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_cidiag::List& CloneContext::Diagnostics() const { 109cb93a386Sopenharmony_ci return dst->Diagnostics(); 110cb93a386Sopenharmony_ci} 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_ciCloneContext::CloneableTransform::CloneableTransform() = default; 113cb93a386Sopenharmony_ciCloneContext::CloneableTransform::CloneableTransform( 114cb93a386Sopenharmony_ci const CloneableTransform&) = default; 115cb93a386Sopenharmony_ciCloneContext::CloneableTransform::~CloneableTransform() = default; 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_ci} // namespace tint 118