blob: 457522bf8ba8c891cce3fd07f9d4ccae7e595568 [file] [log] [blame]
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001// Copyright 2020 The Tint Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "src/tint/clone_context.h"
16
17#include <string>
18
19#include "src/tint/program_builder.h"
20#include "src/tint/utils/map.h"
21
22TINT_INSTANTIATE_TYPEINFO(tint::Cloneable);
23
24namespace tint {
25
dan sinclair3a2a2792022-06-29 14:38:15 +000026Cloneable::Cloneable() = default;
27Cloneable::Cloneable(Cloneable&&) = default;
28Cloneable::~Cloneable() = default;
29
dan sinclair41e4d9a2022-05-01 14:40:55 +000030CloneContext::CloneContext(ProgramBuilder* to, Program const* from, bool auto_clone_symbols)
Ryan Harrisondbc13af2022-02-21 15:19:07 +000031 : dst(to), src(from) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000032 if (auto_clone_symbols) {
33 // Almost all transforms will want to clone all symbols before doing any
34 // work, to avoid any newly created symbols clashing with existing symbols
35 // in the source program and causing them to be renamed.
36 from->Symbols().Foreach([&](Symbol s, const std::string&) { Clone(s); });
37 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000038}
39
dan sinclair41e4d9a2022-05-01 14:40:55 +000040CloneContext::CloneContext(ProgramBuilder* builder) : CloneContext(builder, nullptr, false) {}
Ryan Harrisondbc13af2022-02-21 15:19:07 +000041
42CloneContext::~CloneContext() = default;
43
44Symbol CloneContext::Clone(Symbol s) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000045 if (!src) {
46 return s; // In-place clone
Ryan Harrisondbc13af2022-02-21 15:19:07 +000047 }
Ben Clayton18dc3152022-08-23 18:38:35 +000048 return cloned_symbols_.GetOrCreate(s, [&]() -> Symbol {
dan sinclair41e4d9a2022-05-01 14:40:55 +000049 if (symbol_transform_) {
50 return symbol_transform_(s);
51 }
52 return dst->Symbols().New(src->Symbols().NameFor(s));
53 });
Ryan Harrisondbc13af2022-02-21 15:19:07 +000054}
55
56void CloneContext::Clone() {
dan sinclair41e4d9a2022-05-01 14:40:55 +000057 dst->AST().Copy(this, &src->AST());
Ryan Harrisondbc13af2022-02-21 15:19:07 +000058}
59
60ast::FunctionList CloneContext::Clone(const ast::FunctionList& v) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000061 ast::FunctionList out;
Ben Clayton783b1692022-08-02 17:03:35 +000062 out.Reserve(v.Length());
dan sinclair41e4d9a2022-05-01 14:40:55 +000063 for (const ast::Function* el : v) {
64 out.Add(Clone(el));
65 }
66 return out;
Ryan Harrisondbc13af2022-02-21 15:19:07 +000067}
68
69const tint::Cloneable* CloneContext::CloneCloneable(const Cloneable* object) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000070 // If the input is nullptr, there's nothing to clone - just return nullptr.
71 if (object == nullptr) {
72 return nullptr;
Ryan Harrisondbc13af2022-02-21 15:19:07 +000073 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000074
dan sinclair41e4d9a2022-05-01 14:40:55 +000075 // Was Replace() called for this object?
Ben Clayton18dc3152022-08-23 18:38:35 +000076 if (auto* fn = replacements_.Find(object)) {
77 return (*fn)();
dan sinclair41e4d9a2022-05-01 14:40:55 +000078 }
79
80 // Attempt to clone using the registered replacer functions.
81 auto& typeinfo = object->TypeInfo();
82 for (auto& transform : transforms_) {
83 if (typeinfo.Is(transform.typeinfo)) {
84 if (auto* transformed = transform.function(object)) {
85 return transformed;
86 }
87 break;
88 }
89 }
90
91 // No transform for this type, or the transform returned nullptr.
92 // Clone with T::Clone().
93 return object->Clone(this);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000094}
95
dan sinclair41e4d9a2022-05-01 14:40:55 +000096void CloneContext::CheckedCastFailure(const Cloneable* got, const TypeInfo& expected) {
97 TINT_ICE(Clone, Diagnostics()) << "Cloned object was not of the expected type\n"
98 << "got: " << got->TypeInfo().name << "\n"
99 << "expected: " << expected.name;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000100}
101
102diag::List& CloneContext::Diagnostics() const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000103 return dst->Diagnostics();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000104}
105
106CloneContext::CloneableTransform::CloneableTransform() = default;
dan sinclair41e4d9a2022-05-01 14:40:55 +0000107CloneContext::CloneableTransform::CloneableTransform(const CloneableTransform&) = default;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000108CloneContext::CloneableTransform::~CloneableTransform() = default;
109
110} // namespace tint