Roll external/abseil_cpp/ 8f739d18b..917bfee46 (2 commits) (#5887)
[KhronosGroup/SPIRV-Tools.git] / source / fuzz / fuzzer_pass_interchange_signedness_of_integer_operands.cpp
blobd8780ff747a2b4524f1c317f2909eae251e062d8
1 // Copyright (c) 2020 Google LLC
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.
15 #include "fuzzer_pass_interchange_signedness_of_integer_operands.h"
17 #include "source/fuzz/fuzzer_util.h"
18 #include "source/fuzz/id_use_descriptor.h"
19 #include "source/fuzz/transformation_record_synonymous_constants.h"
20 #include "source/fuzz/transformation_replace_id_with_synonym.h"
22 namespace spvtools {
23 namespace fuzz {
25 FuzzerPassInterchangeSignednessOfIntegerOperands::
26 FuzzerPassInterchangeSignednessOfIntegerOperands(
27 opt::IRContext* ir_context,
28 TransformationContext* transformation_context,
29 FuzzerContext* fuzzer_context,
30 protobufs::TransformationSequence* transformations,
31 bool ignore_inapplicable_transformations)
32 : FuzzerPass(ir_context, transformation_context, fuzzer_context,
33 transformations, ignore_inapplicable_transformations) {}
35 void FuzzerPassInterchangeSignednessOfIntegerOperands::Apply() {
36 assert(!GetFuzzerContext()->IsWgslCompatible() &&
37 "Cannot interchange signedness in WGSL");
39 // Make vector keeping track of all the uses we want to replace.
40 // This is a vector of pairs, where the first element is an id use descriptor
41 // identifying the use of a constant id and the second is the id that should
42 // be used to replace it.
43 std::vector<std::pair<protobufs::IdUseDescriptor, uint32_t>> uses_to_replace;
45 for (auto constant : GetIRContext()->GetConstants()) {
46 uint32_t constant_id = constant->result_id();
48 // We want to record the synonymity of an integer constant with another
49 // constant with opposite signedness, and this can only be done if they are
50 // not irrelevant.
51 if (GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
52 constant_id)) {
53 continue;
56 uint32_t toggled_id =
57 FindOrCreateToggledIntegerConstant(constant->result_id());
58 if (!toggled_id) {
59 // Not an integer constant
60 continue;
63 assert(!GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
64 toggled_id) &&
65 "FindOrCreateToggledConstant can't produce an irrelevant id");
67 // Record synonymous constants
68 ApplyTransformation(
69 TransformationRecordSynonymousConstants(constant_id, toggled_id));
71 // Find all the uses of the constant and, for each, probabilistically
72 // decide whether to replace it.
73 GetIRContext()->get_def_use_mgr()->ForEachUse(
74 constant_id,
75 [this, toggled_id, &uses_to_replace](opt::Instruction* use_inst,
76 uint32_t use_index) -> void {
77 if (GetFuzzerContext()->ChoosePercentage(
78 GetFuzzerContext()
79 ->GetChanceOfInterchangingSignednessOfIntegerOperands())) {
80 MaybeAddUseToReplace(use_inst, use_index, toggled_id,
81 &uses_to_replace);
83 });
86 // Replace the ids if it is allowed.
87 for (auto use_to_replace : uses_to_replace) {
88 MaybeApplyTransformation(TransformationReplaceIdWithSynonym(
89 use_to_replace.first, use_to_replace.second));
93 uint32_t FuzzerPassInterchangeSignednessOfIntegerOperands::
94 FindOrCreateToggledIntegerConstant(uint32_t id) {
95 // |id| must not be a specialization constant because we do not know the value
96 // of specialization constants.
97 if (opt::IsSpecConstantInst(
98 GetIRContext()->get_def_use_mgr()->GetDef(id)->opcode())) {
99 return 0;
102 auto constant = GetIRContext()->get_constant_mgr()->FindDeclaredConstant(id);
104 // This pass only toggles integer constants.
105 if (!constant->AsIntConstant() &&
106 (!constant->AsVectorConstant() ||
107 !constant->AsVectorConstant()->component_type()->AsInteger())) {
108 return 0;
111 if (auto integer = constant->AsIntConstant()) {
112 auto type = integer->type()->AsInteger();
114 // Find or create and return the toggled constant.
115 return FindOrCreateIntegerConstant(std::vector<uint32_t>(integer->words()),
116 type->width(), !type->IsSigned(), false);
119 // The constant is an integer vector.
121 // Find the component type.
122 auto component_type =
123 constant->AsVectorConstant()->component_type()->AsInteger();
125 // Find or create the toggled component type.
126 uint32_t toggled_component_type = FindOrCreateIntegerType(
127 component_type->width(), !component_type->IsSigned());
129 // Get the information about the toggled components. We need to extract this
130 // information now because the analyses might be invalidated, which would make
131 // the constant and component_type variables invalid.
132 std::vector<std::vector<uint32_t>> component_words;
134 for (auto component : constant->AsVectorConstant()->GetComponents()) {
135 component_words.push_back(component->AsIntConstant()->words());
137 uint32_t width = component_type->width();
138 bool is_signed = !component_type->IsSigned();
140 std::vector<uint32_t> toggled_components;
142 // Find or create the toggled components.
143 for (auto words : component_words) {
144 toggled_components.push_back(
145 FindOrCreateIntegerConstant(words, width, is_signed, false));
148 // Find or create the required toggled vector type.
149 uint32_t toggled_type = FindOrCreateVectorType(
150 toggled_component_type, (uint32_t)toggled_components.size());
152 // Find or create and return the toggled vector constant.
153 return FindOrCreateCompositeConstant(toggled_components, toggled_type, false);
156 } // namespace fuzz
157 } // namespace spvtools