• 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 #ifndef SRC_SEM_STATEMENT_H_
16 #define SRC_SEM_STATEMENT_H_
17 
18 #include "src/sem/behavior.h"
19 #include "src/sem/node.h"
20 
21 // Forward declarations
22 namespace tint {
23 namespace ast {
24 class Function;
25 class Statement;
26 }  // namespace ast
27 namespace sem {
28 class BlockStatement;
29 }  // namespace sem
30 }  // namespace tint
31 
32 namespace tint {
33 namespace sem {
34 
35 /// Forward declaration
36 class CompoundStatement;
37 class Function;
38 
39 namespace detail {
40 /// FindFirstParentReturn is a traits helper for determining the return type for
41 /// the template member function Statement::FindFirstParent().
42 /// For zero or multiple template arguments, FindFirstParentReturn::type
43 /// resolves to CompoundStatement.
44 template <typename... TYPES>
45 struct FindFirstParentReturn {
46   /// The pointer type returned by Statement::FindFirstParent()
47   using type = CompoundStatement;
48 };
49 
50 /// A specialization of FindFirstParentReturn for a single template argument.
51 /// FindFirstParentReturn::type resolves to the single template argument.
52 template <typename T>
53 struct FindFirstParentReturn<T> {
54   /// The pointer type returned by Statement::FindFirstParent()
55   using type = T;
56 };
57 
58 template <typename... TYPES>
59 using FindFirstParentReturnType =
60     typename FindFirstParentReturn<TYPES...>::type;
61 }  // namespace detail
62 
63 /// Statement holds the semantic information for a statement.
64 class Statement : public Castable<Statement, Node> {
65  public:
66   /// Constructor
67   /// @param declaration the AST node for this statement
68   /// @param parent the owning statement
69   /// @param function the owning function
70   Statement(const ast::Statement* declaration,
71             const CompoundStatement* parent,
72             const sem::Function* function);
73 
74   /// Destructor
75   ~Statement() override;
76 
77   /// @return the AST node for this statement
78   const ast::Statement* Declaration() const { return declaration_; }
79 
80   /// @return the statement that encloses this statement
81   const CompoundStatement* Parent() const { return parent_; }
82 
83   /// @returns the closest enclosing parent that satisfies the given predicate,
84   /// which may be the statement itself, or nullptr if no match is found.
85   /// @param pred a predicate that the resulting block must satisfy
86   template <typename Pred>
87   const CompoundStatement* FindFirstParent(Pred&& pred) const;
88 
89   /// @returns the closest enclosing parent that is of one of the types in
90   /// `TYPES`, which may be the statement itself, or nullptr if no match is
91   /// found. If `TYPES` is a single template argument, the return type is a
92   /// pointer to that template argument type, otherwise a CompoundStatement
93   /// pointer is returned.
94   template <typename... TYPES>
95   const detail::FindFirstParentReturnType<TYPES...>* FindFirstParent() const;
96 
97   /// @return the closest enclosing block for this statement
98   const BlockStatement* Block() const;
99 
100   /// @returns the function that owns this statement
101   const sem::Function* Function() const { return function_; }
102 
103   /// @return the behaviors of this statement
104   const sem::Behaviors& Behaviors() const { return behaviors_; }
105 
106   /// @return the behaviors of this statement
107   sem::Behaviors& Behaviors() { return behaviors_; }
108 
109   /// @returns true if this statement is reachable by control flow according to
110   /// the behavior analysis
111   bool IsReachable() const { return is_reachable_; }
112 
113   /// @param is_reachable whether this statement is reachable by control flow
114   /// according to the behavior analysis
115   void SetIsReachable(bool is_reachable) { is_reachable_ = is_reachable; }
116 
117  private:
118   const ast::Statement* const declaration_;
119   const CompoundStatement* const parent_;
120   const sem::Function* const function_;
121   sem::Behaviors behaviors_{sem::Behavior::kNext};
122   bool is_reachable_ = true;
123 };
124 
125 /// CompoundStatement is the base class of statements that can hold other
126 /// statements.
127 class CompoundStatement : public Castable<Statement, Statement> {
128  public:
129   /// Constructor
130   /// @param declaration the AST node for this statement
131   /// @param statement the owning statement
132   /// @param function the owning function
133   CompoundStatement(const ast::Statement* declaration,
134                     const CompoundStatement* statement,
135                     const sem::Function* function);
136 
137   /// Destructor
138   ~CompoundStatement() override;
139 };
140 
141 template <typename Pred>
142 const CompoundStatement* Statement::FindFirstParent(Pred&& pred) const {
143   if (auto* self = As<CompoundStatement>()) {
144     if (pred(self)) {
145       return self;
146     }
147   }
148   const auto* curr = parent_;
149   while (curr && !pred(curr)) {
150     curr = curr->Parent();
151   }
152   return curr;
153 }
154 
155 template <typename... TYPES>
156 const detail::FindFirstParentReturnType<TYPES...>* Statement::FindFirstParent()
157     const {
158   using ReturnType = detail::FindFirstParentReturnType<TYPES...>;
159   if (sizeof...(TYPES) == 1) {
160     if (auto* p = As<ReturnType>()) {
161       return p;
162     }
163     const auto* curr = parent_;
164     while (curr) {
165       if (auto* p = curr->As<ReturnType>()) {
166         return p;
167       }
168       curr = curr->Parent();
169     }
170   } else {
171     if (IsAnyOf<TYPES...>()) {
172       return As<ReturnType>();
173     }
174     const auto* curr = parent_;
175     while (curr) {
176       if (curr->IsAnyOf<TYPES...>()) {
177         return curr->As<ReturnType>();
178       }
179       curr = curr->Parent();
180     }
181   }
182   return nullptr;
183 }
184 
185 }  // namespace sem
186 }  // namespace tint
187 
188 #endif  // SRC_SEM_STATEMENT_H_
189