• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2020 Stefano Milizia
2 // Copyright (c) 2020 Google LLC
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include "source/fuzz/fuzzer_pass_interchange_zero_like_constants.h"
17 
18 #include "source/fuzz/fuzzer_util.h"
19 #include "source/fuzz/id_use_descriptor.h"
20 #include "source/fuzz/transformation_record_synonymous_constants.h"
21 #include "source/fuzz/transformation_replace_id_with_synonym.h"
22 
23 namespace spvtools {
24 namespace fuzz {
FuzzerPassInterchangeZeroLikeConstants(opt::IRContext * ir_context,TransformationContext * transformation_context,FuzzerContext * fuzzer_context,protobufs::TransformationSequence * transformations,bool ignore_inapplicable_transformations)25 FuzzerPassInterchangeZeroLikeConstants::FuzzerPassInterchangeZeroLikeConstants(
26     opt::IRContext* ir_context, TransformationContext* transformation_context,
27     FuzzerContext* fuzzer_context,
28     protobufs::TransformationSequence* transformations,
29     bool ignore_inapplicable_transformations)
30     : FuzzerPass(ir_context, transformation_context, fuzzer_context,
31                  transformations, ignore_inapplicable_transformations) {}
32 
FindOrCreateToggledConstant(opt::Instruction * declaration)33 uint32_t FuzzerPassInterchangeZeroLikeConstants::FindOrCreateToggledConstant(
34     opt::Instruction* declaration) {
35   // |declaration| must not be a specialization constant because we do not know
36   // the value of specialization constants.
37   if (opt::IsSpecConstantInst(declaration->opcode())) {
38     return 0;
39   }
40 
41   auto constant = GetIRContext()->get_constant_mgr()->FindDeclaredConstant(
42       declaration->result_id());
43 
44   // This pass only toggles zero-like constants
45   if (!constant->IsZero()) {
46     return 0;
47   }
48 
49   if (constant->AsScalarConstant()) {
50     return FindOrCreateNullConstant(declaration->type_id());
51   } else if (constant->AsNullConstant()) {
52     // Add declaration of equivalent scalar constant
53     auto kind = constant->type()->kind();
54     if (kind == opt::analysis::Type::kBool ||
55         kind == opt::analysis::Type::kInteger ||
56         kind == opt::analysis::Type::kFloat) {
57       return FindOrCreateZeroConstant(declaration->type_id(), false);
58     }
59   }
60 
61   return 0;
62 }
63 
Apply()64 void FuzzerPassInterchangeZeroLikeConstants::Apply() {
65   // Make vector keeping track of all the uses we want to replace.
66   // This is a vector of pairs, where the first element is an id use descriptor
67   // identifying the use of a constant id and the second is the id that should
68   // be used to replace it.
69   std::vector<std::pair<protobufs::IdUseDescriptor, uint32_t>> uses_to_replace;
70 
71   for (auto constant : GetIRContext()->GetConstants()) {
72     uint32_t constant_id = constant->result_id();
73     if (GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
74             constant_id)) {
75       continue;
76     }
77 
78     uint32_t toggled_id = FindOrCreateToggledConstant(constant);
79     if (!toggled_id) {
80       // Not a zero-like constant
81       continue;
82     }
83 
84     assert(!GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
85                toggled_id) &&
86            "FindOrCreateToggledConstant can't produce an irrelevant id");
87 
88     // Record synonymous constants
89     ApplyTransformation(
90         TransformationRecordSynonymousConstants(constant_id, toggled_id));
91 
92     // Find all the uses of the constant and, for each, probabilistically
93     // decide whether to replace it.
94     GetIRContext()->get_def_use_mgr()->ForEachUse(
95         constant_id,
96         [this, toggled_id, &uses_to_replace](opt::Instruction* use_inst,
97                                              uint32_t use_index) -> void {
98           if (GetFuzzerContext()->ChoosePercentage(
99                   GetFuzzerContext()
100                       ->GetChanceOfInterchangingZeroLikeConstants())) {
101             MaybeAddUseToReplace(use_inst, use_index, toggled_id,
102                                  &uses_to_replace);
103           }
104         });
105   }
106 
107   // Replace the ids if it is allowed.
108   for (auto use_to_replace : uses_to_replace) {
109     MaybeApplyTransformation(TransformationReplaceIdWithSynonym(
110         use_to_replace.first, use_to_replace.second));
111   }
112 }
113 }  // namespace fuzz
114 }  // namespace spvtools
115