• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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/clone_context.h"
16 
17 #include <string>
18 
19 #include "src/program_builder.h"
20 #include "src/utils/map.h"
21 
22 TINT_INSTANTIATE_TYPEINFO(tint::Cloneable);
23 
24 namespace tint {
25 
26 CloneContext::ListTransforms::ListTransforms() = default;
27 CloneContext::ListTransforms::~ListTransforms() = default;
28 
CloneContext(ProgramBuilder * to,Program const * from,bool auto_clone_symbols)29 CloneContext::CloneContext(ProgramBuilder* to,
30                            Program const* from,
31                            bool auto_clone_symbols)
32     : dst(to), src(from) {
33   if (auto_clone_symbols) {
34     // Almost all transforms will want to clone all symbols before doing any
35     // work, to avoid any newly created symbols clashing with existing symbols
36     // in the source program and causing them to be renamed.
37     from->Symbols().Foreach([&](Symbol s, const std::string&) { Clone(s); });
38   }
39 }
40 
CloneContext(ProgramBuilder * builder)41 CloneContext::CloneContext(ProgramBuilder* builder)
42     : CloneContext(builder, nullptr, false) {}
43 
44 CloneContext::~CloneContext() = default;
45 
Clone(Symbol s)46 Symbol CloneContext::Clone(Symbol s) {
47   if (!src) {
48     return s;  // In-place clone
49   }
50   return utils::GetOrCreate(cloned_symbols_, s, [&]() -> Symbol {
51     if (symbol_transform_) {
52       return symbol_transform_(s);
53     }
54     return dst->Symbols().New(src->Symbols().NameFor(s));
55   });
56 }
57 
Clone()58 void CloneContext::Clone() {
59   dst->AST().Copy(this, &src->AST());
60   dst->SetTransformApplied(src->TransformsApplied());
61 }
62 
Clone(const ast::FunctionList & v)63 ast::FunctionList CloneContext::Clone(const ast::FunctionList& v) {
64   ast::FunctionList out;
65   out.reserve(v.size());
66   for (const ast::Function* el : v) {
67     out.Add(Clone(el));
68   }
69   return out;
70 }
71 
CloneCloneable(const Cloneable * object)72 const tint::Cloneable* CloneContext::CloneCloneable(const Cloneable* object) {
73   // If the input is nullptr, there's nothing to clone - just return nullptr.
74   if (object == nullptr) {
75     return nullptr;
76   }
77 
78   // Was Replace() called for this object?
79   auto it = replacements_.find(object);
80   if (it != replacements_.end()) {
81     return it->second();
82   }
83 
84   // Attempt to clone using the registered replacer functions.
85   auto& typeinfo = object->TypeInfo();
86   for (auto& transform : transforms_) {
87     if (typeinfo.Is(*transform.typeinfo)) {
88       if (auto* transformed = transform.function(object)) {
89         return transformed;
90       }
91       break;
92     }
93   }
94 
95   // No transform for this type, or the transform returned nullptr.
96   // Clone with T::Clone().
97   return object->Clone(this);
98 }
99 
CheckedCastFailure(const Cloneable * got,const TypeInfo & expected)100 void CloneContext::CheckedCastFailure(const Cloneable* got,
101                                       const TypeInfo& expected) {
102   TINT_ICE(Clone, Diagnostics())
103       << "Cloned object was not of the expected type\n"
104       << "got:      " << got->TypeInfo().name << "\n"
105       << "expected: " << expected.name;
106 }
107 
Diagnostics() const108 diag::List& CloneContext::Diagnostics() const {
109   return dst->Diagnostics();
110 }
111 
112 CloneContext::CloneableTransform::CloneableTransform() = default;
113 CloneContext::CloneableTransform::CloneableTransform(
114     const CloneableTransform&) = default;
115 CloneContext::CloneableTransform::~CloneableTransform() = default;
116 
117 }  // namespace tint
118