1 // Copyright (c) 2020 Vasyl Teliman 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 #ifndef SOURCE_FUZZ_TRANSFORMATION_ADD_SYNONYM_H_ 16 #define SOURCE_FUZZ_TRANSFORMATION_ADD_SYNONYM_H_ 17 18 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h" 19 #include "source/fuzz/transformation.h" 20 #include "source/fuzz/transformation_context.h" 21 #include "source/opt/ir_context.h" 22 23 namespace spvtools { 24 namespace fuzz { 25 26 class TransformationAddSynonym : public Transformation { 27 public: 28 explicit TransformationAddSynonym( 29 protobufs::TransformationAddSynonym message); 30 31 TransformationAddSynonym( 32 uint32_t result_id, 33 protobufs::TransformationAddSynonym::SynonymType synonym_type, 34 uint32_t synonym_fresh_id, 35 const protobufs::InstructionDescriptor& insert_before); 36 37 // - |result_id| must be a valid result id of some instruction in the module. 38 // - |result_id| may not be an irrelevant id. 39 // - |synonym_type| is a type of the synonymous instruction that will be 40 // created. 41 // - |synonym_fresh_id| is a fresh id. 42 // - |insert_before| must be a valid instruction descriptor and we must be 43 // able to insert a new synonymous instruction before |insert_before|. 44 // - |result_id| must be available before |insert_before|. 45 bool IsApplicable( 46 opt::IRContext* ir_context, 47 const TransformationContext& transformation_context) const override; 48 49 // Creates a new synonymous instruction according to the |synonym_type| with 50 // result id |synonym_fresh_id|. 51 // Inserts that instruction before |insert_before| and creates a fact 52 // that the |synonym_fresh_id| and the |result_id| are synonymous. 53 void Apply(opt::IRContext* ir_context, 54 TransformationContext* transformation_context) const override; 55 56 std::unordered_set<uint32_t> GetFreshIds() const override; 57 58 protobufs::Transformation ToMessage() const override; 59 60 // Returns true if we can create a synonym of |inst| according to the 61 // |synonym_type|. 62 static bool IsInstructionValid( 63 opt::IRContext* ir_context, 64 const TransformationContext& transformation_context, 65 opt::Instruction* inst, 66 protobufs::TransformationAddSynonym::SynonymType synonym_type); 67 68 // Returns true if |synonym_type| requires an additional constant instruction 69 // to be present in the module. 70 static bool IsAdditionalConstantRequired( 71 protobufs::TransformationAddSynonym::SynonymType synonym_type); 72 73 private: 74 // Returns a new instruction which is synonymous to |message_.result_id|. 75 std::unique_ptr<opt::Instruction> MakeSynonymousInstruction( 76 opt::IRContext* ir_context, 77 const TransformationContext& transformation_context) const; 78 79 // Returns a result id of a constant instruction that is required to be 80 // present in some synonym types (e.g. returns a result id of a zero constant 81 // for ADD_ZERO synonym type). Returns 0 if no such instruction is present in 82 // the module. This method should only be called when 83 // IsAdditionalConstantRequired returns true. 84 uint32_t MaybeGetConstantId( 85 opt::IRContext* ir_context, 86 const TransformationContext& transformation_context) const; 87 88 protobufs::TransformationAddSynonym message_; 89 }; 90 91 } // namespace fuzz 92 } // namespace spvtools 93 94 #endif // SOURCE_FUZZ_TRANSFORMATION_ADD_SYNONYM_H_ 95