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