spirv-fuzz: Permute the order of variables at function scope issue (#4248)

Fixes #4194.
This commit is contained in:
Mostafa Ashraf 2021-04-26 17:53:55 +02:00 committed by GitHub
parent 22b82872b4
commit 8fe39ad581
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 562 additions and 2 deletions

View File

@ -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

View File

@ -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<opt::IRContext> ir_context,
&final_passes_);
}
MaybeAddFinalPass<FuzzerPassInterchangeZeroLikeConstants>(&final_passes_);
MaybeAddFinalPass<FuzzerPassPermuteFunctionVariables>(&final_passes_);
MaybeAddFinalPass<FuzzerPassPermutePhiOperands>(&final_passes_);
MaybeAddFinalPass<FuzzerPassSwapCommutableOperands>(&final_passes_);
MaybeAddFinalPass<FuzzerPassToggleAccessChainInstruction>(&final_passes_);

View File

@ -120,6 +120,8 @@ const std::pair<uint32_t, uint32_t> kChanceOfMovingBlockDown = {20, 50};
const std::pair<uint32_t, uint32_t> kChanceOfMutatingPointer = {20, 90};
const std::pair<uint32_t, uint32_t> kChanceOfObfuscatingConstant = {10, 90};
const std::pair<uint32_t, uint32_t> kChanceOfOutliningFunction = {10, 90};
const std::pair<uint32_t, uint32_t> kChanceOfPermutingFunctionVariables = {30,
90};
const std::pair<uint32_t, uint32_t> kChanceOfPermutingInstructions = {20, 70};
const std::pair<uint32_t, uint32_t> kChanceOfPermutingParameters = {30, 90};
const std::pair<uint32_t, uint32_t> kChanceOfPermutingPhiOperands = {30, 90};
@ -153,6 +155,8 @@ const std::pair<uint32_t, uint32_t> kChanceOfReplacingParametersWithStruct = {
const std::pair<uint32_t, uint32_t> kChanceOfSplittingBlock = {40, 95};
const std::pair<uint32_t, uint32_t> kChanceOfSwappingConditionalBranchOperands =
{10, 70};
const std::pair<uint32_t, uint32_t>
kChanceOfSwappingAnotherPairOfFunctionVariables = {30, 90};
const std::pair<uint32_t, uint32_t> kChanceOfTogglingAccessChainInstruction = {
20, 90};
const std::pair<uint32_t, uint32_t> kChanceOfWrappingRegionInSelection = {70,
@ -315,6 +319,8 @@ FuzzerContext::FuzzerContext(std::unique_ptr<RandomGenerator> 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<RandomGenerator> 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_ =

View File

@ -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_;

View File

@ -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 <algorithm>
#include <numeric>
#include <vector>
#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<opt::Instruction*> 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

View File

@ -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_

View File

@ -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.

View File

@ -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> Transformation::FromMessage(
kSwapConditionalBranchOperands:
return MakeUnique<TransformationSwapConditionalBranchOperands>(
message.swap_conditional_branch_operands());
case protobufs::Transformation::TransformationCase::kSwapFunctionVariables:
return MakeUnique<TransformationSwapFunctionVariables>(
message.swap_function_variables());
case protobufs::Transformation::TransformationCase::
kToggleAccessChainInstruction:
return MakeUnique<TransformationToggleAccessChainInstruction>(

View File

@ -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<uint32_t> TransformationSwapFunctionVariables::GetFreshIds()
const {
return std::unordered_set<uint32_t>();
}
} // namespace fuzz
} // namespace spvtools

View File

@ -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<uint32_t> GetFreshIds() const override;
private:
protobufs::TransformationSwapFunctionVariables message_;
};
} // namespace fuzz
} // namespace spvtools
#endif // SOURCE_FUZZ_TRANSFORMATION_SWAP_FUNCTION_VARIABLES_H_

View File

@ -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

View File

@ -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<FactManager>(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<FactManager>(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

View File

@ -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(