• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 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/transform/unshadow.h"
16 
17 #include <memory>
18 #include <unordered_map>
19 #include <utility>
20 
21 #include "src/program_builder.h"
22 #include "src/sem/block_statement.h"
23 #include "src/sem/function.h"
24 #include "src/sem/statement.h"
25 #include "src/sem/variable.h"
26 
27 TINT_INSTANTIATE_TYPEINFO(tint::transform::Unshadow);
28 
29 namespace tint {
30 namespace transform {
31 
32 /// The PIMPL state for the Unshadow transform
33 struct Unshadow::State {
34   /// The clone context
35   CloneContext& ctx;
36 
37   /// Constructor
38   /// @param context the clone context
Statetint::transform::Unshadow::State39   explicit State(CloneContext& context) : ctx(context) {}
40 
41   /// Performs the transformation
Runtint::transform::Unshadow::State42   void Run() {
43     auto& sem = ctx.src->Sem();
44 
45     // Maps a variable to its new name.
46     std::unordered_map<const sem::Variable*, Symbol> renamed_to;
47 
48     auto rename = [&](const sem::Variable* var) -> const ast::Variable* {
49       auto* decl = var->Declaration();
50       auto name = ctx.src->Symbols().NameFor(decl->symbol);
51       auto symbol = ctx.dst->Symbols().New(name);
52       renamed_to.emplace(var, symbol);
53 
54       auto source = ctx.Clone(decl->source);
55       auto* type = ctx.Clone(decl->type);
56       auto* constructor = ctx.Clone(decl->constructor);
57       auto decorations = ctx.Clone(decl->decorations);
58       return ctx.dst->create<ast::Variable>(
59           source, symbol, decl->declared_storage_class, decl->declared_access,
60           type, decl->is_const, constructor, decorations);
61     };
62 
63     ctx.ReplaceAll([&](const ast::Variable* var) -> const ast::Variable* {
64       if (auto* local = sem.Get<sem::LocalVariable>(var)) {
65         if (local->Shadows()) {
66           return rename(local);
67         }
68       }
69       if (auto* param = sem.Get<sem::Parameter>(var)) {
70         if (param->Shadows()) {
71           return rename(param);
72         }
73       }
74       return nullptr;
75     });
76     ctx.ReplaceAll([&](const ast::IdentifierExpression* ident)
77                        -> const tint::ast::IdentifierExpression* {
78       if (auto* user = sem.Get<sem::VariableUser>(ident)) {
79         auto it = renamed_to.find(user->Variable());
80         if (it != renamed_to.end()) {
81           return ctx.dst->Expr(it->second);
82         }
83       }
84       return nullptr;
85     });
86     ctx.Clone();
87   }
88 };
89 
90 Unshadow::Unshadow() = default;
91 
92 Unshadow::~Unshadow() = default;
93 
Run(CloneContext & ctx,const DataMap &,DataMap &)94 void Unshadow::Run(CloneContext& ctx, const DataMap&, DataMap&) {
95   State(ctx).Run();
96 }
97 
98 }  // namespace transform
99 }  // namespace tint
100