1 // Copyright (c) 2019 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. 14 15 #include "source/fuzz/transformation.h" 16 17 #include <cassert> 18 19 #include "source/fuzz/fuzzer_util.h" 20 #include "source/fuzz/transformation_access_chain.h" 21 #include "source/fuzz/transformation_add_constant_boolean.h" 22 #include "source/fuzz/transformation_add_constant_composite.h" 23 #include "source/fuzz/transformation_add_constant_null.h" 24 #include "source/fuzz/transformation_add_constant_scalar.h" 25 #include "source/fuzz/transformation_add_dead_block.h" 26 #include "source/fuzz/transformation_add_dead_break.h" 27 #include "source/fuzz/transformation_add_dead_continue.h" 28 #include "source/fuzz/transformation_add_function.h" 29 #include "source/fuzz/transformation_add_global_undef.h" 30 #include "source/fuzz/transformation_add_global_variable.h" 31 #include "source/fuzz/transformation_add_local_variable.h" 32 #include "source/fuzz/transformation_add_no_contraction_decoration.h" 33 #include "source/fuzz/transformation_add_type_array.h" 34 #include "source/fuzz/transformation_add_type_boolean.h" 35 #include "source/fuzz/transformation_add_type_float.h" 36 #include "source/fuzz/transformation_add_type_function.h" 37 #include "source/fuzz/transformation_add_type_int.h" 38 #include "source/fuzz/transformation_add_type_matrix.h" 39 #include "source/fuzz/transformation_add_type_pointer.h" 40 #include "source/fuzz/transformation_add_type_struct.h" 41 #include "source/fuzz/transformation_add_type_vector.h" 42 #include "source/fuzz/transformation_composite_construct.h" 43 #include "source/fuzz/transformation_composite_extract.h" 44 #include "source/fuzz/transformation_copy_object.h" 45 #include "source/fuzz/transformation_equation_instruction.h" 46 #include "source/fuzz/transformation_function_call.h" 47 #include "source/fuzz/transformation_load.h" 48 #include "source/fuzz/transformation_merge_blocks.h" 49 #include "source/fuzz/transformation_move_block_down.h" 50 #include "source/fuzz/transformation_outline_function.h" 51 #include "source/fuzz/transformation_permute_function_parameters.h" 52 #include "source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h" 53 #include "source/fuzz/transformation_replace_constant_with_uniform.h" 54 #include "source/fuzz/transformation_replace_id_with_synonym.h" 55 #include "source/fuzz/transformation_set_function_control.h" 56 #include "source/fuzz/transformation_set_loop_control.h" 57 #include "source/fuzz/transformation_set_memory_operands_mask.h" 58 #include "source/fuzz/transformation_set_selection_control.h" 59 #include "source/fuzz/transformation_split_block.h" 60 #include "source/fuzz/transformation_store.h" 61 #include "source/fuzz/transformation_swap_commutable_operands.h" 62 #include "source/fuzz/transformation_toggle_access_chain_instruction.h" 63 #include "source/fuzz/transformation_vector_shuffle.h" 64 #include "source/util/make_unique.h" 65 66 namespace spvtools { 67 namespace fuzz { 68 69 Transformation::~Transformation() = default; 70 FromMessage(const protobufs::Transformation & message)71std::unique_ptr<Transformation> Transformation::FromMessage( 72 const protobufs::Transformation& message) { 73 switch (message.transformation_case()) { 74 case protobufs::Transformation::TransformationCase::kAccessChain: 75 return MakeUnique<TransformationAccessChain>(message.access_chain()); 76 case protobufs::Transformation::TransformationCase::kAddConstantBoolean: 77 return MakeUnique<TransformationAddConstantBoolean>( 78 message.add_constant_boolean()); 79 case protobufs::Transformation::TransformationCase::kAddConstantComposite: 80 return MakeUnique<TransformationAddConstantComposite>( 81 message.add_constant_composite()); 82 case protobufs::Transformation::TransformationCase::kAddConstantNull: 83 return MakeUnique<TransformationAddConstantNull>( 84 message.add_constant_null()); 85 case protobufs::Transformation::TransformationCase::kAddConstantScalar: 86 return MakeUnique<TransformationAddConstantScalar>( 87 message.add_constant_scalar()); 88 case protobufs::Transformation::TransformationCase::kAddDeadBlock: 89 return MakeUnique<TransformationAddDeadBlock>(message.add_dead_block()); 90 case protobufs::Transformation::TransformationCase::kAddDeadBreak: 91 return MakeUnique<TransformationAddDeadBreak>(message.add_dead_break()); 92 case protobufs::Transformation::TransformationCase::kAddDeadContinue: 93 return MakeUnique<TransformationAddDeadContinue>( 94 message.add_dead_continue()); 95 case protobufs::Transformation::TransformationCase::kAddFunction: 96 return MakeUnique<TransformationAddFunction>(message.add_function()); 97 case protobufs::Transformation::TransformationCase::kAddGlobalUndef: 98 return MakeUnique<TransformationAddGlobalUndef>( 99 message.add_global_undef()); 100 case protobufs::Transformation::TransformationCase::kAddGlobalVariable: 101 return MakeUnique<TransformationAddGlobalVariable>( 102 message.add_global_variable()); 103 case protobufs::Transformation::TransformationCase::kAddLocalVariable: 104 return MakeUnique<TransformationAddLocalVariable>( 105 message.add_local_variable()); 106 case protobufs::Transformation::TransformationCase:: 107 kAddNoContractionDecoration: 108 return MakeUnique<TransformationAddNoContractionDecoration>( 109 message.add_no_contraction_decoration()); 110 case protobufs::Transformation::TransformationCase::kAddTypeArray: 111 return MakeUnique<TransformationAddTypeArray>(message.add_type_array()); 112 case protobufs::Transformation::TransformationCase::kAddTypeBoolean: 113 return MakeUnique<TransformationAddTypeBoolean>( 114 message.add_type_boolean()); 115 case protobufs::Transformation::TransformationCase::kAddTypeFloat: 116 return MakeUnique<TransformationAddTypeFloat>(message.add_type_float()); 117 case protobufs::Transformation::TransformationCase::kAddTypeFunction: 118 return MakeUnique<TransformationAddTypeFunction>( 119 message.add_type_function()); 120 case protobufs::Transformation::TransformationCase::kAddTypeInt: 121 return MakeUnique<TransformationAddTypeInt>(message.add_type_int()); 122 case protobufs::Transformation::TransformationCase::kAddTypeMatrix: 123 return MakeUnique<TransformationAddTypeMatrix>(message.add_type_matrix()); 124 case protobufs::Transformation::TransformationCase::kAddTypePointer: 125 return MakeUnique<TransformationAddTypePointer>( 126 message.add_type_pointer()); 127 case protobufs::Transformation::TransformationCase::kAddTypeStruct: 128 return MakeUnique<TransformationAddTypeStruct>(message.add_type_struct()); 129 case protobufs::Transformation::TransformationCase::kAddTypeVector: 130 return MakeUnique<TransformationAddTypeVector>(message.add_type_vector()); 131 case protobufs::Transformation::TransformationCase::kCompositeConstruct: 132 return MakeUnique<TransformationCompositeConstruct>( 133 message.composite_construct()); 134 case protobufs::Transformation::TransformationCase::kCompositeExtract: 135 return MakeUnique<TransformationCompositeExtract>( 136 message.composite_extract()); 137 case protobufs::Transformation::TransformationCase::kCopyObject: 138 return MakeUnique<TransformationCopyObject>(message.copy_object()); 139 case protobufs::Transformation::TransformationCase::kEquationInstruction: 140 return MakeUnique<TransformationEquationInstruction>( 141 message.equation_instruction()); 142 case protobufs::Transformation::TransformationCase::kFunctionCall: 143 return MakeUnique<TransformationFunctionCall>(message.function_call()); 144 case protobufs::Transformation::TransformationCase::kLoad: 145 return MakeUnique<TransformationLoad>(message.load()); 146 case protobufs::Transformation::TransformationCase::kMergeBlocks: 147 return MakeUnique<TransformationMergeBlocks>(message.merge_blocks()); 148 case protobufs::Transformation::TransformationCase::kMoveBlockDown: 149 return MakeUnique<TransformationMoveBlockDown>(message.move_block_down()); 150 case protobufs::Transformation::TransformationCase::kOutlineFunction: 151 return MakeUnique<TransformationOutlineFunction>( 152 message.outline_function()); 153 case protobufs::Transformation::TransformationCase:: 154 kPermuteFunctionParameters: 155 return MakeUnique<TransformationPermuteFunctionParameters>( 156 message.permute_function_parameters()); 157 case protobufs::Transformation::TransformationCase:: 158 kReplaceBooleanConstantWithConstantBinary: 159 return MakeUnique<TransformationReplaceBooleanConstantWithConstantBinary>( 160 message.replace_boolean_constant_with_constant_binary()); 161 case protobufs::Transformation::TransformationCase:: 162 kReplaceConstantWithUniform: 163 return MakeUnique<TransformationReplaceConstantWithUniform>( 164 message.replace_constant_with_uniform()); 165 case protobufs::Transformation::TransformationCase::kReplaceIdWithSynonym: 166 return MakeUnique<TransformationReplaceIdWithSynonym>( 167 message.replace_id_with_synonym()); 168 case protobufs::Transformation::TransformationCase::kSetFunctionControl: 169 return MakeUnique<TransformationSetFunctionControl>( 170 message.set_function_control()); 171 case protobufs::Transformation::TransformationCase::kSetLoopControl: 172 return MakeUnique<TransformationSetLoopControl>( 173 message.set_loop_control()); 174 case protobufs::Transformation::TransformationCase::kSetMemoryOperandsMask: 175 return MakeUnique<TransformationSetMemoryOperandsMask>( 176 message.set_memory_operands_mask()); 177 case protobufs::Transformation::TransformationCase::kSetSelectionControl: 178 return MakeUnique<TransformationSetSelectionControl>( 179 message.set_selection_control()); 180 case protobufs::Transformation::TransformationCase::kSplitBlock: 181 return MakeUnique<TransformationSplitBlock>(message.split_block()); 182 case protobufs::Transformation::TransformationCase::kStore: 183 return MakeUnique<TransformationStore>(message.store()); 184 case protobufs::Transformation::TransformationCase::kSwapCommutableOperands: 185 return MakeUnique<TransformationSwapCommutableOperands>( 186 message.swap_commutable_operands()); 187 case protobufs::Transformation::TransformationCase:: 188 kToggleAccessChainInstruction: 189 return MakeUnique<TransformationToggleAccessChainInstruction>( 190 message.toggle_access_chain_instruction()); 191 case protobufs::Transformation::TransformationCase::kVectorShuffle: 192 return MakeUnique<TransformationVectorShuffle>(message.vector_shuffle()); 193 case protobufs::Transformation::TRANSFORMATION_NOT_SET: 194 assert(false && "An unset transformation was encountered."); 195 return nullptr; 196 } 197 assert(false && "Should be unreachable as all cases must be handled above."); 198 return nullptr; 199 } 200 CheckIdIsFreshAndNotUsedByThisTransformation(uint32_t id,opt::IRContext * ir_context,std::set<uint32_t> * ids_used_by_this_transformation)201bool Transformation::CheckIdIsFreshAndNotUsedByThisTransformation( 202 uint32_t id, opt::IRContext* ir_context, 203 std::set<uint32_t>* ids_used_by_this_transformation) { 204 if (!fuzzerutil::IsFreshId(ir_context, id)) { 205 return false; 206 } 207 if (ids_used_by_this_transformation->count(id) != 0) { 208 return false; 209 } 210 ids_used_by_this_transformation->insert(id); 211 return true; 212 } 213 214 } // namespace fuzz 215 } // namespace spvtools 216