spirv-fuzz: Permute the order of variables at function scope issue (#4248)
Fixes #4194.
This commit is contained in:
Родитель
22b82872b4
Коммит
8fe39ad581
|
@ -101,6 +101,7 @@ if(SPIRV_BUILD_FUZZER)
|
||||||
fuzzer_pass_outline_functions.h
|
fuzzer_pass_outline_functions.h
|
||||||
fuzzer_pass_permute_blocks.h
|
fuzzer_pass_permute_blocks.h
|
||||||
fuzzer_pass_permute_function_parameters.h
|
fuzzer_pass_permute_function_parameters.h
|
||||||
|
fuzzer_pass_permute_function_variables.h
|
||||||
fuzzer_pass_permute_instructions.h
|
fuzzer_pass_permute_instructions.h
|
||||||
fuzzer_pass_permute_phi_operands.h
|
fuzzer_pass_permute_phi_operands.h
|
||||||
fuzzer_pass_propagate_instructions_down.h
|
fuzzer_pass_propagate_instructions_down.h
|
||||||
|
@ -222,6 +223,7 @@ if(SPIRV_BUILD_FUZZER)
|
||||||
transformation_store.h
|
transformation_store.h
|
||||||
transformation_swap_commutable_operands.h
|
transformation_swap_commutable_operands.h
|
||||||
transformation_swap_conditional_branch_operands.h
|
transformation_swap_conditional_branch_operands.h
|
||||||
|
transformation_swap_function_variables.h
|
||||||
transformation_toggle_access_chain_instruction.h
|
transformation_toggle_access_chain_instruction.h
|
||||||
transformation_vector_shuffle.h
|
transformation_vector_shuffle.h
|
||||||
transformation_wrap_early_terminator_in_function.h
|
transformation_wrap_early_terminator_in_function.h
|
||||||
|
@ -292,6 +294,7 @@ if(SPIRV_BUILD_FUZZER)
|
||||||
fuzzer_pass_outline_functions.cpp
|
fuzzer_pass_outline_functions.cpp
|
||||||
fuzzer_pass_permute_blocks.cpp
|
fuzzer_pass_permute_blocks.cpp
|
||||||
fuzzer_pass_permute_function_parameters.cpp
|
fuzzer_pass_permute_function_parameters.cpp
|
||||||
|
fuzzer_pass_permute_function_variables.cpp
|
||||||
fuzzer_pass_permute_instructions.cpp
|
fuzzer_pass_permute_instructions.cpp
|
||||||
fuzzer_pass_permute_phi_operands.cpp
|
fuzzer_pass_permute_phi_operands.cpp
|
||||||
fuzzer_pass_propagate_instructions_down.cpp
|
fuzzer_pass_propagate_instructions_down.cpp
|
||||||
|
@ -411,6 +414,7 @@ if(SPIRV_BUILD_FUZZER)
|
||||||
transformation_store.cpp
|
transformation_store.cpp
|
||||||
transformation_swap_commutable_operands.cpp
|
transformation_swap_commutable_operands.cpp
|
||||||
transformation_swap_conditional_branch_operands.cpp
|
transformation_swap_conditional_branch_operands.cpp
|
||||||
|
transformation_swap_function_variables.cpp
|
||||||
transformation_toggle_access_chain_instruction.cpp
|
transformation_toggle_access_chain_instruction.cpp
|
||||||
transformation_vector_shuffle.cpp
|
transformation_vector_shuffle.cpp
|
||||||
transformation_wrap_early_terminator_in_function.cpp
|
transformation_wrap_early_terminator_in_function.cpp
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
#include "source/fuzz/fuzzer_pass_outline_functions.h"
|
#include "source/fuzz/fuzzer_pass_outline_functions.h"
|
||||||
#include "source/fuzz/fuzzer_pass_permute_blocks.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_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_instructions.h"
|
||||||
#include "source/fuzz/fuzzer_pass_permute_phi_operands.h"
|
#include "source/fuzz/fuzzer_pass_permute_phi_operands.h"
|
||||||
#include "source/fuzz/fuzzer_pass_propagate_instructions_down.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_);
|
&final_passes_);
|
||||||
}
|
}
|
||||||
MaybeAddFinalPass<FuzzerPassInterchangeZeroLikeConstants>(&final_passes_);
|
MaybeAddFinalPass<FuzzerPassInterchangeZeroLikeConstants>(&final_passes_);
|
||||||
|
MaybeAddFinalPass<FuzzerPassPermuteFunctionVariables>(&final_passes_);
|
||||||
MaybeAddFinalPass<FuzzerPassPermutePhiOperands>(&final_passes_);
|
MaybeAddFinalPass<FuzzerPassPermutePhiOperands>(&final_passes_);
|
||||||
MaybeAddFinalPass<FuzzerPassSwapCommutableOperands>(&final_passes_);
|
MaybeAddFinalPass<FuzzerPassSwapCommutableOperands>(&final_passes_);
|
||||||
MaybeAddFinalPass<FuzzerPassToggleAccessChainInstruction>(&final_passes_);
|
MaybeAddFinalPass<FuzzerPassToggleAccessChainInstruction>(&final_passes_);
|
||||||
|
|
|
@ -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> kChanceOfMutatingPointer = {20, 90};
|
||||||
const std::pair<uint32_t, uint32_t> kChanceOfObfuscatingConstant = {10, 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> 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> kChanceOfPermutingInstructions = {20, 70};
|
||||||
const std::pair<uint32_t, uint32_t> kChanceOfPermutingParameters = {30, 90};
|
const std::pair<uint32_t, uint32_t> kChanceOfPermutingParameters = {30, 90};
|
||||||
const std::pair<uint32_t, uint32_t> kChanceOfPermutingPhiOperands = {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> kChanceOfSplittingBlock = {40, 95};
|
||||||
const std::pair<uint32_t, uint32_t> kChanceOfSwappingConditionalBranchOperands =
|
const std::pair<uint32_t, uint32_t> kChanceOfSwappingConditionalBranchOperands =
|
||||||
{10, 70};
|
{10, 70};
|
||||||
|
const std::pair<uint32_t, uint32_t>
|
||||||
|
kChanceOfSwappingAnotherPairOfFunctionVariables = {30, 90};
|
||||||
const std::pair<uint32_t, uint32_t> kChanceOfTogglingAccessChainInstruction = {
|
const std::pair<uint32_t, uint32_t> kChanceOfTogglingAccessChainInstruction = {
|
||||||
20, 90};
|
20, 90};
|
||||||
const std::pair<uint32_t, uint32_t> kChanceOfWrappingRegionInSelection = {70,
|
const std::pair<uint32_t, uint32_t> kChanceOfWrappingRegionInSelection = {70,
|
||||||
|
@ -315,6 +319,8 @@ FuzzerContext::FuzzerContext(std::unique_ptr<RandomGenerator> random_generator,
|
||||||
ChooseBetweenMinAndMax(kChanceOfObfuscatingConstant);
|
ChooseBetweenMinAndMax(kChanceOfObfuscatingConstant);
|
||||||
chance_of_outlining_function_ =
|
chance_of_outlining_function_ =
|
||||||
ChooseBetweenMinAndMax(kChanceOfOutliningFunction);
|
ChooseBetweenMinAndMax(kChanceOfOutliningFunction);
|
||||||
|
chance_of_permuting_function_variables_ =
|
||||||
|
ChooseBetweenMinAndMax(kChanceOfPermutingFunctionVariables);
|
||||||
chance_of_permuting_instructions_ =
|
chance_of_permuting_instructions_ =
|
||||||
ChooseBetweenMinAndMax(kChanceOfPermutingInstructions);
|
ChooseBetweenMinAndMax(kChanceOfPermutingInstructions);
|
||||||
chance_of_permuting_parameters_ =
|
chance_of_permuting_parameters_ =
|
||||||
|
@ -352,6 +358,8 @@ FuzzerContext::FuzzerContext(std::unique_ptr<RandomGenerator> random_generator,
|
||||||
chance_of_replacing_parameters_with_struct_ =
|
chance_of_replacing_parameters_with_struct_ =
|
||||||
ChooseBetweenMinAndMax(kChanceOfReplacingParametersWithStruct);
|
ChooseBetweenMinAndMax(kChanceOfReplacingParametersWithStruct);
|
||||||
chance_of_splitting_block_ = ChooseBetweenMinAndMax(kChanceOfSplittingBlock);
|
chance_of_splitting_block_ = ChooseBetweenMinAndMax(kChanceOfSplittingBlock);
|
||||||
|
chance_of_swapping_another_pair_of_function_variables_ =
|
||||||
|
ChooseBetweenMinAndMax(kChanceOfSwappingAnotherPairOfFunctionVariables);
|
||||||
chance_of_swapping_conditional_branch_operands_ =
|
chance_of_swapping_conditional_branch_operands_ =
|
||||||
ChooseBetweenMinAndMax(kChanceOfSwappingConditionalBranchOperands);
|
ChooseBetweenMinAndMax(kChanceOfSwappingConditionalBranchOperands);
|
||||||
chance_of_toggling_access_chain_instruction_ =
|
chance_of_toggling_access_chain_instruction_ =
|
||||||
|
|
|
@ -303,6 +303,9 @@ class FuzzerContext {
|
||||||
uint32_t GetChanceOfOutliningFunction() const {
|
uint32_t GetChanceOfOutliningFunction() const {
|
||||||
return chance_of_outlining_function_;
|
return chance_of_outlining_function_;
|
||||||
}
|
}
|
||||||
|
uint32_t GetChanceOfPermutingFunctionVariables() const {
|
||||||
|
return chance_of_permuting_function_variables_;
|
||||||
|
}
|
||||||
uint32_t GetChanceOfPermutingInstructions() const {
|
uint32_t GetChanceOfPermutingInstructions() const {
|
||||||
return chance_of_permuting_instructions_;
|
return chance_of_permuting_instructions_;
|
||||||
}
|
}
|
||||||
|
@ -360,6 +363,9 @@ class FuzzerContext {
|
||||||
uint32_t GetChanceOfSplittingBlock() const {
|
uint32_t GetChanceOfSplittingBlock() const {
|
||||||
return chance_of_splitting_block_;
|
return chance_of_splitting_block_;
|
||||||
}
|
}
|
||||||
|
uint32_t GetChanceOfSwappingAnotherPairOfFunctionVariables() const {
|
||||||
|
return chance_of_swapping_another_pair_of_function_variables_;
|
||||||
|
}
|
||||||
uint32_t GetChanceOfSwappingConditionalBranchOperands() const {
|
uint32_t GetChanceOfSwappingConditionalBranchOperands() const {
|
||||||
return chance_of_swapping_conditional_branch_operands_;
|
return chance_of_swapping_conditional_branch_operands_;
|
||||||
}
|
}
|
||||||
|
@ -526,6 +532,7 @@ class FuzzerContext {
|
||||||
uint32_t chance_of_mutating_pointer_;
|
uint32_t chance_of_mutating_pointer_;
|
||||||
uint32_t chance_of_obfuscating_constant_;
|
uint32_t chance_of_obfuscating_constant_;
|
||||||
uint32_t chance_of_outlining_function_;
|
uint32_t chance_of_outlining_function_;
|
||||||
|
uint32_t chance_of_permuting_function_variables_;
|
||||||
uint32_t chance_of_permuting_instructions_;
|
uint32_t chance_of_permuting_instructions_;
|
||||||
uint32_t chance_of_permuting_parameters_;
|
uint32_t chance_of_permuting_parameters_;
|
||||||
uint32_t chance_of_permuting_phi_operands_;
|
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_globals_;
|
||||||
uint32_t chance_of_replacing_parameters_with_struct_;
|
uint32_t chance_of_replacing_parameters_with_struct_;
|
||||||
uint32_t chance_of_splitting_block_;
|
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_swapping_conditional_branch_operands_;
|
||||||
uint32_t chance_of_toggling_access_chain_instruction_;
|
uint32_t chance_of_toggling_access_chain_instruction_;
|
||||||
uint32_t chance_of_wrapping_region_in_selection_;
|
uint32_t chance_of_wrapping_region_in_selection_;
|
||||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -557,6 +557,7 @@ message Transformation {
|
||||||
TransformationWrapEarlyTerminatorInFunction wrap_early_terminator_in_function = 83;
|
TransformationWrapEarlyTerminatorInFunction wrap_early_terminator_in_function = 83;
|
||||||
TransformationMergeFunctionReturns merge_function_returns = 84;
|
TransformationMergeFunctionReturns merge_function_returns = 84;
|
||||||
TransformationExpandVectorReduction expand_vector_reduction = 85;
|
TransformationExpandVectorReduction expand_vector_reduction = 85;
|
||||||
|
TransformationSwapFunctionVariables swap_function_variables = 86;
|
||||||
// Add additional option using the next available number.
|
// 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 {
|
message TransformationToggleAccessChainInstruction {
|
||||||
|
|
||||||
// A transformation that toggles an access chain instruction.
|
// A transformation that toggles an access chain instruction.
|
||||||
|
|
|
@ -98,6 +98,7 @@
|
||||||
#include "source/fuzz/transformation_store.h"
|
#include "source/fuzz/transformation_store.h"
|
||||||
#include "source/fuzz/transformation_swap_commutable_operands.h"
|
#include "source/fuzz/transformation_swap_commutable_operands.h"
|
||||||
#include "source/fuzz/transformation_swap_conditional_branch_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_toggle_access_chain_instruction.h"
|
||||||
#include "source/fuzz/transformation_vector_shuffle.h"
|
#include "source/fuzz/transformation_vector_shuffle.h"
|
||||||
#include "source/fuzz/transformation_wrap_early_terminator_in_function.h"
|
#include "source/fuzz/transformation_wrap_early_terminator_in_function.h"
|
||||||
|
@ -361,6 +362,9 @@ std::unique_ptr<Transformation> Transformation::FromMessage(
|
||||||
kSwapConditionalBranchOperands:
|
kSwapConditionalBranchOperands:
|
||||||
return MakeUnique<TransformationSwapConditionalBranchOperands>(
|
return MakeUnique<TransformationSwapConditionalBranchOperands>(
|
||||||
message.swap_conditional_branch_operands());
|
message.swap_conditional_branch_operands());
|
||||||
|
case protobufs::Transformation::TransformationCase::kSwapFunctionVariables:
|
||||||
|
return MakeUnique<TransformationSwapFunctionVariables>(
|
||||||
|
message.swap_function_variables());
|
||||||
case protobufs::Transformation::TransformationCase::
|
case protobufs::Transformation::TransformationCase::
|
||||||
kToggleAccessChainInstruction:
|
kToggleAccessChainInstruction:
|
||||||
return MakeUnique<TransformationToggleAccessChainInstruction>(
|
return MakeUnique<TransformationToggleAccessChainInstruction>(
|
||||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -114,6 +114,7 @@ if (${SPIRV_BUILD_FUZZER})
|
||||||
transformation_store_test.cpp
|
transformation_store_test.cpp
|
||||||
transformation_swap_commutable_operands_test.cpp
|
transformation_swap_commutable_operands_test.cpp
|
||||||
transformation_swap_conditional_branch_operands_test.cpp
|
transformation_swap_conditional_branch_operands_test.cpp
|
||||||
|
transformation_swap_function_variables_test.cpp
|
||||||
transformation_toggle_access_chain_instruction_test.cpp
|
transformation_toggle_access_chain_instruction_test.cpp
|
||||||
transformation_record_synonymous_constants_test.cpp
|
transformation_record_synonymous_constants_test.cpp
|
||||||
transformation_vector_shuffle_test.cpp
|
transformation_vector_shuffle_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<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
|
|
@ -37,8 +37,9 @@ AUTHORS = ['The Khronos Group Inc.',
|
||||||
'Vasyl Teliman',
|
'Vasyl Teliman',
|
||||||
'Advanced Micro Devices, Inc.',
|
'Advanced Micro Devices, Inc.',
|
||||||
'Stefano Milizia',
|
'Stefano Milizia',
|
||||||
'Alastair F. Donaldson']
|
'Alastair F. Donaldson',
|
||||||
CURRENT_YEAR='2020'
|
'Mostafa Ashraf']
|
||||||
|
CURRENT_YEAR='2021'
|
||||||
|
|
||||||
YEARS = '(2014-2016|2015-2016|2015-2020|2016|2016-2017|2017|2017-2019|2018|2019|2020|2021)'
|
YEARS = '(2014-2016|2015-2016|2015-2020|2016|2016-2017|2017|2017-2019|2018|2019|2020|2021)'
|
||||||
COPYRIGHT_RE = re.compile(
|
COPYRIGHT_RE = re.compile(
|
||||||
|
|
Загрузка…
Ссылка в новой задаче