• 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 FUZZERS_TINT_AST_FUZZER_UTIL_H_
16 #define FUZZERS_TINT_AST_FUZZER_UTIL_H_
17 
18 #include <vector>
19 
20 #include "src/ast/module.h"
21 #include "src/ast/variable_decl_statement.h"
22 #include "src/castable.h"
23 #include "src/program.h"
24 #include "src/sem/block_statement.h"
25 #include "src/sem/function.h"
26 #include "src/sem/statement.h"
27 #include "src/sem/variable.h"
28 
29 namespace tint {
30 namespace fuzzers {
31 namespace ast_fuzzer {
32 namespace util {
33 /// @file
34 
35 /// @brief Returns all in-scope variables (including formal function parameters)
36 /// related to statement `curr_stmt`.
37 ///
38 /// These variables are additionally filtered by applying a predicate `pred`.
39 ///
40 /// @tparam Pred - a predicate that accepts a `const sem::Variable*` and returns
41 ///     `bool`.
42 /// @param program - the program to look for variables in.
43 /// @param curr_stmt - the current statement. Everything below it is not in
44 ///     scope.
45 /// @param pred - a predicate (e.g. a function pointer, functor, lambda etc) of
46 ///     type `Pred`.
47 /// @return a vector of all variables that can be accessed from `curr_stmt`.
48 template <typename Pred>
GetAllVarsInScope(const tint::Program & program,const sem::Statement * curr_stmt,Pred && pred)49 std::vector<const sem::Variable*> GetAllVarsInScope(
50     const tint::Program& program,
51     const sem::Statement* curr_stmt,
52     Pred&& pred) {
53   std::vector<const sem::Variable*> result;
54 
55   // Walk up the hierarchy of blocks in which `curr_stmt` is contained.
56   for (const auto* block = curr_stmt->Block(); block;
57        block = tint::As<sem::BlockStatement>(block->Parent())) {
58     for (const auto* stmt : block->Declaration()->statements) {
59       if (stmt == curr_stmt->Declaration()) {
60         // `curr_stmt` was found. This is only possible if `block is the
61         // enclosing block of `curr_stmt` since the AST nodes are not shared.
62         // Because of all this, skip the iteration of the inner loop since
63         // the rest of the instructions in the `block` are not visible from the
64         // `curr_stmt`.
65         break;
66       }
67 
68       if (const auto* var_node = tint::As<ast::VariableDeclStatement>(stmt)) {
69         const auto* sem_var = program.Sem().Get(var_node->variable);
70         if (pred(sem_var)) {
71           result.push_back(sem_var);
72         }
73       }
74     }
75   }
76 
77   // Process function parameters.
78   for (const auto* param : curr_stmt->Function()->Parameters()) {
79     if (pred(param)) {
80       result.push_back(param);
81     }
82   }
83 
84   // Global variables do not belong to any ast::BlockStatement.
85   for (const auto* global_decl : program.AST().GlobalDeclarations()) {
86     if (global_decl == curr_stmt->Function()->Declaration()) {
87       // The same situation as in the previous loop. The current function has
88       // been reached. If there are any variables declared below, they won't be
89       // visible in this function. Thus, exit the loop.
90       break;
91     }
92 
93     if (const auto* global_var = tint::As<ast::Variable>(global_decl)) {
94       const auto* sem_node = program.Sem().Get(global_var);
95       if (pred(sem_node)) {
96         result.push_back(sem_node);
97       }
98     }
99   }
100 
101   return result;
102 }
103 
104 }  // namespace util
105 }  // namespace ast_fuzzer
106 }  // namespace fuzzers
107 }  // namespace tint
108 
109 #endif  // FUZZERS_TINT_AST_FUZZER_UTIL_H_
110