• 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 "fuzzers/tint_ast_fuzzer/mutation_finders/replace_identifiers.h"
16 
17 #include <memory>
18 
19 #include "fuzzers/tint_ast_fuzzer/mutations/replace_identifier.h"
20 #include "fuzzers/tint_ast_fuzzer/util.h"
21 
22 #include "src/sem/expression.h"
23 #include "src/sem/statement.h"
24 #include "src/sem/variable.h"
25 
26 namespace tint {
27 namespace fuzzers {
28 namespace ast_fuzzer {
29 
FindMutations(const tint::Program & program,NodeIdMap * node_id_map,ProbabilityContext * probability_context) const30 MutationList MutationFinderReplaceIdentifiers::FindMutations(
31     const tint::Program& program,
32     NodeIdMap* node_id_map,
33     ProbabilityContext* probability_context) const {
34   MutationList result;
35 
36   // Go through each variable in the AST and for each user of that variable, try
37   // to replace it with some other variable usage.
38 
39   for (const auto* node : program.SemNodes().Objects()) {
40     const auto* sem_variable = tint::As<sem::Variable>(node);
41     if (!sem_variable) {
42       continue;
43     }
44 
45     // Iterate over all users of `sem_variable`.
46     for (const auto* user : sem_variable->Users()) {
47       // Get all variables that can be used to replace the `user` of
48       // `sem_variable`.
49       auto candidate_variables = util::GetAllVarsInScope(
50           program, user->Stmt(), [user](const sem::Variable* var) {
51             return var != user->Variable() && var->Type() == user->Type();
52           });
53 
54       if (candidate_variables.empty()) {
55         // No suitable replacements have been found.
56         continue;
57       }
58 
59       const auto* replacement =
60           candidate_variables[probability_context->GetRandomIndex(
61               candidate_variables)];
62 
63       result.push_back(std::make_unique<MutationReplaceIdentifier>(
64           node_id_map->GetId(user->Declaration()),
65           node_id_map->GetId(replacement->Declaration())));
66     }
67   }
68 
69   return result;
70 }
71 
GetChanceOfApplyingMutation(ProbabilityContext * probability_context) const72 uint32_t MutationFinderReplaceIdentifiers::GetChanceOfApplyingMutation(
73     ProbabilityContext* probability_context) const {
74   return probability_context->GetChanceOfReplacingIdentifiers();
75 }
76 
77 }  // namespace ast_fuzzer
78 }  // namespace fuzzers
79 }  // namespace tint
80