diff --git a/source/fuzz/CMakeLists.txt b/source/fuzz/CMakeLists.txt index 804fcf07..5601a0d9 100644 --- a/source/fuzz/CMakeLists.txt +++ b/source/fuzz/CMakeLists.txt @@ -101,6 +101,7 @@ if(SPIRV_BUILD_FUZZER) fuzzer_pass_outline_functions.h fuzzer_pass_permute_blocks.h fuzzer_pass_permute_function_parameters.h + fuzzer_pass_permute_function_variables.h fuzzer_pass_permute_instructions.h fuzzer_pass_permute_phi_operands.h fuzzer_pass_propagate_instructions_down.h @@ -222,6 +223,7 @@ if(SPIRV_BUILD_FUZZER) transformation_store.h transformation_swap_commutable_operands.h transformation_swap_conditional_branch_operands.h + transformation_swap_function_variables.h transformation_toggle_access_chain_instruction.h transformation_vector_shuffle.h transformation_wrap_early_terminator_in_function.h @@ -292,6 +294,7 @@ if(SPIRV_BUILD_FUZZER) fuzzer_pass_outline_functions.cpp fuzzer_pass_permute_blocks.cpp fuzzer_pass_permute_function_parameters.cpp + fuzzer_pass_permute_function_variables.cpp fuzzer_pass_permute_instructions.cpp fuzzer_pass_permute_phi_operands.cpp fuzzer_pass_propagate_instructions_down.cpp @@ -411,6 +414,7 @@ if(SPIRV_BUILD_FUZZER) transformation_store.cpp transformation_swap_commutable_operands.cpp transformation_swap_conditional_branch_operands.cpp + transformation_swap_function_variables.cpp transformation_toggle_access_chain_instruction.cpp transformation_vector_shuffle.cpp transformation_wrap_early_terminator_in_function.cpp diff --git a/source/fuzz/fuzzer.cpp b/source/fuzz/fuzzer.cpp index 9d1af752..45cfac46 100644 --- a/source/fuzz/fuzzer.cpp +++ b/source/fuzz/fuzzer.cpp @@ -67,6 +67,7 @@ #include "source/fuzz/fuzzer_pass_outline_functions.h" #include "source/fuzz/fuzzer_pass_permute_blocks.h" #include "source/fuzz/fuzzer_pass_permute_function_parameters.h" +#include "source/fuzz/fuzzer_pass_permute_function_variables.h" #include "source/fuzz/fuzzer_pass_permute_instructions.h" #include "source/fuzz/fuzzer_pass_permute_phi_operands.h" #include "source/fuzz/fuzzer_pass_propagate_instructions_down.h" @@ -236,6 +237,7 @@ Fuzzer::Fuzzer(std::unique_ptr ir_context, &final_passes_); } MaybeAddFinalPass(&final_passes_); + MaybeAddFinalPass(&final_passes_); MaybeAddFinalPass(&final_passes_); MaybeAddFinalPass(&final_passes_); MaybeAddFinalPass(&final_passes_); diff --git a/source/fuzz/fuzzer_context.cpp b/source/fuzz/fuzzer_context.cpp index ef93e719..47da7944 100644 --- a/source/fuzz/fuzzer_context.cpp +++ b/source/fuzz/fuzzer_context.cpp @@ -120,6 +120,8 @@ const std::pair kChanceOfMovingBlockDown = {20, 50}; const std::pair kChanceOfMutatingPointer = {20, 90}; const std::pair kChanceOfObfuscatingConstant = {10, 90}; const std::pair kChanceOfOutliningFunction = {10, 90}; +const std::pair kChanceOfPermutingFunctionVariables = {30, + 90}; const std::pair kChanceOfPermutingInstructions = {20, 70}; const std::pair kChanceOfPermutingParameters = {30, 90}; const std::pair kChanceOfPermutingPhiOperands = {30, 90}; @@ -153,6 +155,8 @@ const std::pair kChanceOfReplacingParametersWithStruct = { const std::pair kChanceOfSplittingBlock = {40, 95}; const std::pair kChanceOfSwappingConditionalBranchOperands = {10, 70}; +const std::pair + kChanceOfSwappingAnotherPairOfFunctionVariables = {30, 90}; const std::pair kChanceOfTogglingAccessChainInstruction = { 20, 90}; const std::pair kChanceOfWrappingRegionInSelection = {70, @@ -315,6 +319,8 @@ FuzzerContext::FuzzerContext(std::unique_ptr random_generator, ChooseBetweenMinAndMax(kChanceOfObfuscatingConstant); chance_of_outlining_function_ = ChooseBetweenMinAndMax(kChanceOfOutliningFunction); + chance_of_permuting_function_variables_ = + ChooseBetweenMinAndMax(kChanceOfPermutingFunctionVariables); chance_of_permuting_instructions_ = ChooseBetweenMinAndMax(kChanceOfPermutingInstructions); chance_of_permuting_parameters_ = @@ -352,6 +358,8 @@ FuzzerContext::FuzzerContext(std::unique_ptr random_generator, chance_of_replacing_parameters_with_struct_ = ChooseBetweenMinAndMax(kChanceOfReplacingParametersWithStruct); chance_of_splitting_block_ = ChooseBetweenMinAndMax(kChanceOfSplittingBlock); + chance_of_swapping_another_pair_of_function_variables_ = + ChooseBetweenMinAndMax(kChanceOfSwappingAnotherPairOfFunctionVariables); chance_of_swapping_conditional_branch_operands_ = ChooseBetweenMinAndMax(kChanceOfSwappingConditionalBranchOperands); chance_of_toggling_access_chain_instruction_ = diff --git a/source/fuzz/fuzzer_context.h b/source/fuzz/fuzzer_context.h index 40fd8783..db2a0745 100644 --- a/source/fuzz/fuzzer_context.h +++ b/source/fuzz/fuzzer_context.h @@ -303,6 +303,9 @@ class FuzzerContext { uint32_t GetChanceOfOutliningFunction() const { return chance_of_outlining_function_; } + uint32_t GetChanceOfPermutingFunctionVariables() const { + return chance_of_permuting_function_variables_; + } uint32_t GetChanceOfPermutingInstructions() const { return chance_of_permuting_instructions_; } @@ -360,6 +363,9 @@ class FuzzerContext { uint32_t GetChanceOfSplittingBlock() const { return chance_of_splitting_block_; } + uint32_t GetChanceOfSwappingAnotherPairOfFunctionVariables() const { + return chance_of_swapping_another_pair_of_function_variables_; + } uint32_t GetChanceOfSwappingConditionalBranchOperands() const { return chance_of_swapping_conditional_branch_operands_; } @@ -526,6 +532,7 @@ class FuzzerContext { uint32_t chance_of_mutating_pointer_; uint32_t chance_of_obfuscating_constant_; uint32_t chance_of_outlining_function_; + uint32_t chance_of_permuting_function_variables_; uint32_t chance_of_permuting_instructions_; uint32_t chance_of_permuting_parameters_; uint32_t chance_of_permuting_phi_operands_; @@ -545,6 +552,7 @@ class FuzzerContext { uint32_t chance_of_replacing_parameters_with_globals_; uint32_t chance_of_replacing_parameters_with_struct_; uint32_t chance_of_splitting_block_; + uint32_t chance_of_swapping_another_pair_of_function_variables_; uint32_t chance_of_swapping_conditional_branch_operands_; uint32_t chance_of_toggling_access_chain_instruction_; uint32_t chance_of_wrapping_region_in_selection_; diff --git a/source/fuzz/fuzzer_pass_permute_function_variables.cpp b/source/fuzz/fuzzer_pass_permute_function_variables.cpp new file mode 100644 index 00000000..af831180 --- /dev/null +++ b/source/fuzz/fuzzer_pass_permute_function_variables.cpp @@ -0,0 +1,70 @@ +// Copyright (c) 2021 Mostafa Ashraf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/fuzzer_pass_permute_function_variables.h" + +#include +#include +#include + +#include "source/fuzz/fuzzer_context.h" +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/instruction_descriptor.h" +#include "source/fuzz/transformation_swap_function_variables.h" + +namespace spvtools { +namespace fuzz { + +FuzzerPassPermuteFunctionVariables::FuzzerPassPermuteFunctionVariables( + opt::IRContext* ir_context, TransformationContext* transformation_context, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations) + : FuzzerPass(ir_context, transformation_context, fuzzer_context, + transformations) {} // Here we call parent constructor + +void FuzzerPassPermuteFunctionVariables::Apply() { + // Permuting OpVariable instructions in each function + for (auto& function : *GetIRContext()->module()) { + if (!GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext()->GetChanceOfPermutingFunctionVariables())) { + continue; + } + + auto first_block = function.entry().get(); + + std::vector variables; + for (auto& instruction : *first_block) { + if (instruction.opcode() == SpvOpVariable) { + variables.push_back(&instruction); + } + } + + do { + uint32_t instruction_1_index = GetFuzzerContext()->RandomIndex(variables); + uint32_t instruction_2_index = GetFuzzerContext()->RandomIndex(variables); + + if (instruction_1_index != instruction_2_index) { + ApplyTransformation(TransformationSwapFunctionVariables( + variables[instruction_1_index]->result_id(), + variables[instruction_2_index]->result_id())); + } + + } while (GetFuzzerContext()->ChoosePercentage( + GetFuzzerContext() + ->GetChanceOfSwappingAnotherPairOfFunctionVariables())); + } +} + +} // namespace fuzz +} // namespace spvtools diff --git a/source/fuzz/fuzzer_pass_permute_function_variables.h b/source/fuzz/fuzzer_pass_permute_function_variables.h new file mode 100644 index 00000000..47f1de28 --- /dev/null +++ b/source/fuzz/fuzzer_pass_permute_function_variables.h @@ -0,0 +1,37 @@ +// Copyright (c) 2021 Mostafa Ashraf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_FUZZER_PASS_PERMUTE_FUNCTION_VARIABLES_H_ +#define SOURCE_FUZZ_FUZZER_PASS_PERMUTE_FUNCTION_VARIABLES_H_ + +#include "source/fuzz/fuzzer_pass.h" + +namespace spvtools { +namespace fuzz { + +// This fuzzer pass permutes variables in functions in the module. +class FuzzerPassPermuteFunctionVariables : public FuzzerPass { + public: + FuzzerPassPermuteFunctionVariables( + opt::IRContext* ir_context, TransformationContext* transformation_context, + FuzzerContext* fuzzer_context, + protobufs::TransformationSequence* transformations); + + void Apply() override; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_FUZZER_PASS_PERMUTE_FUNCTION_VARIABLES_H_ diff --git a/source/fuzz/protobufs/spvtoolsfuzz.proto b/source/fuzz/protobufs/spvtoolsfuzz.proto index 770a2dd3..c2879fb0 100644 --- a/source/fuzz/protobufs/spvtoolsfuzz.proto +++ b/source/fuzz/protobufs/spvtoolsfuzz.proto @@ -557,6 +557,7 @@ message Transformation { TransformationWrapEarlyTerminatorInFunction wrap_early_terminator_in_function = 83; TransformationMergeFunctionReturns merge_function_returns = 84; TransformationExpandVectorReduction expand_vector_reduction = 85; + TransformationSwapFunctionVariables swap_function_variables = 86; // Add additional option using the next available number. } } @@ -2260,6 +2261,15 @@ message TransformationSwapConditionalBranchOperands { } +message TransformationSwapFunctionVariables { + // A transformation that swaps function variables + + // Result id of the first variable. + uint32 result_id1 = 1; + // Result id of the second variable. + uint32 result_id2 = 2; +} + message TransformationToggleAccessChainInstruction { // A transformation that toggles an access chain instruction. diff --git a/source/fuzz/transformation.cpp b/source/fuzz/transformation.cpp index ebbc3937..c27b5823 100644 --- a/source/fuzz/transformation.cpp +++ b/source/fuzz/transformation.cpp @@ -98,6 +98,7 @@ #include "source/fuzz/transformation_store.h" #include "source/fuzz/transformation_swap_commutable_operands.h" #include "source/fuzz/transformation_swap_conditional_branch_operands.h" +#include "source/fuzz/transformation_swap_function_variables.h" #include "source/fuzz/transformation_toggle_access_chain_instruction.h" #include "source/fuzz/transformation_vector_shuffle.h" #include "source/fuzz/transformation_wrap_early_terminator_in_function.h" @@ -361,6 +362,9 @@ std::unique_ptr Transformation::FromMessage( kSwapConditionalBranchOperands: return MakeUnique( message.swap_conditional_branch_operands()); + case protobufs::Transformation::TransformationCase::kSwapFunctionVariables: + return MakeUnique( + message.swap_function_variables()); case protobufs::Transformation::TransformationCase:: kToggleAccessChainInstruction: return MakeUnique( diff --git a/source/fuzz/transformation_swap_function_variables.cpp b/source/fuzz/transformation_swap_function_variables.cpp new file mode 100644 index 00000000..44cd5953 --- /dev/null +++ b/source/fuzz/transformation_swap_function_variables.cpp @@ -0,0 +1,87 @@ +// Copyright (c) 2021 Mostafa Ashraf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_swap_function_variables.h" + +#include "source/fuzz/fuzzer_util.h" + +namespace spvtools { +namespace fuzz { + +TransformationSwapFunctionVariables::TransformationSwapFunctionVariables( + protobufs::TransformationSwapFunctionVariables message) + : message_(std::move(message)) {} + +TransformationSwapFunctionVariables::TransformationSwapFunctionVariables( + uint32_t result_id1, uint32_t result_id2) { + message_.set_result_id1(result_id1); + message_.set_result_id2(result_id2); +} + +bool TransformationSwapFunctionVariables::IsApplicable( + opt::IRContext* ir_context, const TransformationContext& /*unused*/) const { + uint32_t result_id1 = message_.result_id1(); + uint32_t result_id2 = message_.result_id2(); + + assert((result_id1 != result_id2) && "Two results ids are equal"); + + // The result ids used in the message must refer to instructions. + auto instruction1 = ir_context->get_def_use_mgr()->GetDef(result_id1); + auto instruction2 = ir_context->get_def_use_mgr()->GetDef(result_id2); + if (instruction1 == nullptr || instruction2 == nullptr) { + return false; + } + // Both instructions must be variables. + if (instruction1->opcode() != SpvOpVariable || + instruction2->opcode() != SpvOpVariable) { + return false; + } + + // Both variable instructions must be in some basic block (as they are + // function-local variables), and they must be in the same block (as they need + // to be variables of the same function). + auto* block_1 = ir_context->get_instr_block(result_id1); + auto* block_2 = ir_context->get_instr_block(result_id2); + if (block_1 == nullptr || block_2 == nullptr) { + return false; + } + + return block_1 == block_2; +} + +void TransformationSwapFunctionVariables::Apply( + opt::IRContext* ir_context, TransformationContext* /*unused*/) const { + // The result ids used in the message must refer to instructions. + auto instruction1 = + ir_context->get_def_use_mgr()->GetDef(message_.result_id1()); + auto instruction2 = + ir_context->get_def_use_mgr()->GetDef(message_.result_id2()); + + std::swap(*instruction1, *instruction2); +} + +protobufs::Transformation TransformationSwapFunctionVariables::ToMessage() + const { + protobufs::Transformation result; + *result.mutable_swap_function_variables() = message_; + return result; +} + +std::unordered_set TransformationSwapFunctionVariables::GetFreshIds() + const { + return std::unordered_set(); +} + +} // namespace fuzz +} // namespace spvtools diff --git a/source/fuzz/transformation_swap_function_variables.h b/source/fuzz/transformation_swap_function_variables.h new file mode 100644 index 00000000..eb383f4f --- /dev/null +++ b/source/fuzz/transformation_swap_function_variables.h @@ -0,0 +1,57 @@ +// Copyright (c) 2021 Mostafa Ashraf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SOURCE_FUZZ_TRANSFORMATION_SWAP_FUNCTION_VARIABLES_H_ +#define SOURCE_FUZZ_TRANSFORMATION_SWAP_FUNCTION_VARIABLES_H_ + +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/fuzz/transformation_context.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +// A transformation that swaps two variable declaration instructions that appear +// in the same function. +class TransformationSwapFunctionVariables : public Transformation { + public: + explicit TransformationSwapFunctionVariables( + protobufs::TransformationSwapFunctionVariables message); + + TransformationSwapFunctionVariables(uint32_t result_id1, uint32_t result_id2); + + // - |message_.result_id1| and |message_.result_id2| must be the ids of + // distinct OpVariable instructions appearing in the same function. + bool IsApplicable( + opt::IRContext* ir_context, + const TransformationContext& transformation_context) const override; + + // Swaps two OpVariable instructions with result ids |message_.result_id1| + // and |message_.result_id2|. + void Apply(opt::IRContext* ir_context, + TransformationContext* transformation_context) const override; + + protobufs::Transformation ToMessage() const override; + + std::unordered_set GetFreshIds() const override; + + private: + protobufs::TransformationSwapFunctionVariables message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_SWAP_FUNCTION_VARIABLES_H_ diff --git a/test/fuzz/CMakeLists.txt b/test/fuzz/CMakeLists.txt index 56fbed81..43536891 100644 --- a/test/fuzz/CMakeLists.txt +++ b/test/fuzz/CMakeLists.txt @@ -114,6 +114,7 @@ if (${SPIRV_BUILD_FUZZER}) transformation_store_test.cpp transformation_swap_commutable_operands_test.cpp transformation_swap_conditional_branch_operands_test.cpp + transformation_swap_function_variables_test.cpp transformation_toggle_access_chain_instruction_test.cpp transformation_record_synonymous_constants_test.cpp transformation_vector_shuffle_test.cpp diff --git a/test/fuzz/transformation_swap_function_variables_test.cpp b/test/fuzz/transformation_swap_function_variables_test.cpp new file mode 100644 index 00000000..a0364968 --- /dev/null +++ b/test/fuzz/transformation_swap_function_variables_test.cpp @@ -0,0 +1,271 @@ +// Copyright (c) 2021 Mostafa Ashraf +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "source/fuzz/transformation_swap_function_variables.h" + +#include "gtest/gtest.h" +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/instruction_descriptor.h" +#include "test/fuzz/fuzz_test_util.h" + +namespace spvtools { +namespace fuzz { +namespace { + +TEST(TransformationSwapFunctionVariables, NotApplicable) { + std::string shader = R"( + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %4 "main" + OpExecutionMode %4 OriginUpperLeft + OpSource ESSL 320 + %2 = OpTypeVoid + %3 = OpTypeFunction %2 + %6 = OpTypeInt 32 1 + %7 = OpTypePointer Function %6 + %8 = OpTypeFloat 32 + %9 = OpTypePointer Function %8 + %10 = OpTypeVector %8 2 + %11 = OpTypePointer Function %10 + %12 = OpTypeVector %8 3 + %13 = OpTypeMatrix %12 3 + %14 = OpTypePointer Function %13 + %15 = OpTypeFunction %2 %7 %9 %11 %14 %7 %7 + %4 = OpFunction %2 None %3 + %5 = OpLabel + %24 = OpVariable %7 Function + %25 = OpVariable %9 Function + %26 = OpVariable %11 Function + %27 = OpVariable %14 Function + %28 = OpVariable %7 Function + %29 = OpVariable %7 Function + %30 = OpVariable %7 Function + %32 = OpVariable %9 Function + %34 = OpVariable %11 Function + %36 = OpVariable %14 Function + %38 = OpVariable %7 Function + %40 = OpVariable %7 Function + %31 = OpLoad %6 %24 + OpStore %30 %31 + %33 = OpLoad %8 %25 + OpStore %32 %33 + %35 = OpLoad %10 %26 + OpStore %34 %35 + %37 = OpLoad %13 %27 + OpStore %36 %37 + %39 = OpLoad %6 %28 + OpStore %38 %39 + %41 = OpLoad %6 %29 + OpStore %40 %41 + %42 = OpFunctionCall %2 %22 %30 %32 %34 %36 %38 %40 + OpReturn + OpFunctionEnd + %22 = OpFunction %2 None %15 + %16 = OpFunctionParameter %7 + %17 = OpFunctionParameter %9 + %18 = OpFunctionParameter %11 + %19 = OpFunctionParameter %14 + %20 = OpFunctionParameter %7 + %21 = OpFunctionParameter %7 + %23 = OpLabel + OpReturn + OpFunctionEnd +)"; + + const auto env = SPV_ENV_UNIVERSAL_1_5; + const auto consumer = nullptr; + const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); + spvtools::ValidatorOptions validator_options; + + ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, + kConsoleMessageConsumer)); + TransformationContext transformation_context( + MakeUnique(context.get()), validator_options); + +#ifndef NDEBUG + // Can't swap variable with itself. + ASSERT_DEATH(TransformationSwapFunctionVariables(7, 7).IsApplicable( + context.get(), transformation_context), + "Two results ids are equal"); +#endif + + // Invalid because 200 is not the id of an instruction. + ASSERT_FALSE(TransformationSwapFunctionVariables(1, 200).IsApplicable( + context.get(), transformation_context)); + // Invalid because 5 is not the id of an instruction. + ASSERT_FALSE(TransformationSwapFunctionVariables(5, 24).IsApplicable( + context.get(), transformation_context)); + // Can't swap two instructions from two different blocks. + ASSERT_FALSE(TransformationSwapFunctionVariables(16, 26).IsApplicable( + context.get(), transformation_context)); +} + +TEST(TransformationSwapFunctionVariables, IsApplicable) { + std::string shader = R"( + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %4 "main" + OpExecutionMode %4 OriginUpperLeft + OpSource ESSL 320 + %2 = OpTypeVoid + %3 = OpTypeFunction %2 + %6 = OpTypeInt 32 1 + %7 = OpTypePointer Function %6 + %8 = OpTypeFloat 32 + %9 = OpTypePointer Function %8 + %10 = OpTypeVector %8 2 + %11 = OpTypePointer Function %10 + %12 = OpTypeVector %8 3 + %13 = OpTypeMatrix %12 3 + %14 = OpTypePointer Function %13 + %15 = OpTypeFunction %2 %7 %9 %11 %14 %7 %7 + %4 = OpFunction %2 None %3 + %5 = OpLabel + %24 = OpVariable %7 Function + %25 = OpVariable %9 Function + %26 = OpVariable %11 Function + %27 = OpVariable %14 Function + %28 = OpVariable %7 Function + %29 = OpVariable %7 Function + %30 = OpVariable %7 Function + %32 = OpVariable %9 Function + %34 = OpVariable %11 Function + %36 = OpVariable %14 Function + %38 = OpVariable %7 Function + %40 = OpVariable %7 Function + %31 = OpLoad %6 %24 + OpStore %30 %31 + %33 = OpLoad %8 %25 + OpStore %32 %33 + %35 = OpLoad %10 %26 + OpStore %34 %35 + %37 = OpLoad %13 %27 + OpStore %36 %37 + %39 = OpLoad %6 %28 + OpStore %38 %39 + %41 = OpLoad %6 %29 + OpStore %40 %41 + %42 = OpFunctionCall %2 %22 %30 %32 %34 %36 %38 %40 + OpReturn + OpFunctionEnd + %22 = OpFunction %2 None %15 + %16 = OpFunctionParameter %7 + %17 = OpFunctionParameter %9 + %18 = OpFunctionParameter %11 + %19 = OpFunctionParameter %14 + %20 = OpFunctionParameter %7 + %21 = OpFunctionParameter %7 + %23 = OpLabel + OpReturn + OpFunctionEnd +)"; + + const auto env = SPV_ENV_UNIVERSAL_1_5; + const auto consumer = nullptr; + const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); + spvtools::ValidatorOptions validator_options; + + ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, + kConsoleMessageConsumer)); + TransformationContext transformation_context( + MakeUnique(context.get()), validator_options); + + // Successful transformations + { + // Swap two OpVariable instructions in the same function. + TransformationSwapFunctionVariables transformation(24, 28); + ASSERT_TRUE( + transformation.IsApplicable(context.get(), transformation_context)); + ApplyAndCheckFreshIds(transformation, context.get(), + &transformation_context); + ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( + context.get(), validator_options, kConsoleMessageConsumer)); + } + { + // Swap two OpVariable instructions in the same function. + TransformationSwapFunctionVariables transformation(38, 40); + ASSERT_TRUE( + transformation.IsApplicable(context.get(), transformation_context)); + ApplyAndCheckFreshIds(transformation, context.get(), + &transformation_context); + ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( + context.get(), validator_options, kConsoleMessageConsumer)); + } + std::string after_transformation = R"( + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %4 "main" + OpExecutionMode %4 OriginUpperLeft + OpSource ESSL 320 + %2 = OpTypeVoid + %3 = OpTypeFunction %2 + %6 = OpTypeInt 32 1 + %7 = OpTypePointer Function %6 + %8 = OpTypeFloat 32 + %9 = OpTypePointer Function %8 + %10 = OpTypeVector %8 2 + %11 = OpTypePointer Function %10 + %12 = OpTypeVector %8 3 + %13 = OpTypeMatrix %12 3 + %14 = OpTypePointer Function %13 + %15 = OpTypeFunction %2 %7 %9 %11 %14 %7 %7 + %4 = OpFunction %2 None %3 + %5 = OpLabel + %28 = OpVariable %7 Function + %25 = OpVariable %9 Function + %26 = OpVariable %11 Function + %27 = OpVariable %14 Function + %24 = OpVariable %7 Function + %29 = OpVariable %7 Function + %30 = OpVariable %7 Function + %32 = OpVariable %9 Function + %34 = OpVariable %11 Function + %36 = OpVariable %14 Function + %40 = OpVariable %7 Function + %38 = OpVariable %7 Function + %31 = OpLoad %6 %24 + OpStore %30 %31 + %33 = OpLoad %8 %25 + OpStore %32 %33 + %35 = OpLoad %10 %26 + OpStore %34 %35 + %37 = OpLoad %13 %27 + OpStore %36 %37 + %39 = OpLoad %6 %28 + OpStore %38 %39 + %41 = OpLoad %6 %29 + OpStore %40 %41 + %42 = OpFunctionCall %2 %22 %30 %32 %34 %36 %38 %40 + OpReturn + OpFunctionEnd + %22 = OpFunction %2 None %15 + %16 = OpFunctionParameter %7 + %17 = OpFunctionParameter %9 + %18 = OpFunctionParameter %11 + %19 = OpFunctionParameter %14 + %20 = OpFunctionParameter %7 + %21 = OpFunctionParameter %7 + %23 = OpLabel + OpReturn + OpFunctionEnd +)"; + ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); +} + +} // namespace +} // namespace fuzz +} // namespace spvtools diff --git a/utils/check_copyright.py b/utils/check_copyright.py index 1bc39f67..6db43281 100755 --- a/utils/check_copyright.py +++ b/utils/check_copyright.py @@ -37,8 +37,9 @@ AUTHORS = ['The Khronos Group Inc.', 'Vasyl Teliman', 'Advanced Micro Devices, Inc.', 'Stefano Milizia', - 'Alastair F. Donaldson'] -CURRENT_YEAR='2020' + 'Alastair F. Donaldson', + 'Mostafa Ashraf'] +CURRENT_YEAR='2021' YEARS = '(2014-2016|2015-2016|2015-2020|2016|2016-2017|2017|2017-2019|2018|2019|2020|2021)' COPYRIGHT_RE = re.compile(