mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-22 11:40:05 +00:00
spirv-fuzz: Permute the order of variables at function scope issue (#4248)
Fixes #4194.
This commit is contained in:
parent
22b82872b4
commit
8fe39ad581
@ -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
|
||||
|
@ -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_);
|
||||
|
@ -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_ =
|
||||
|
@ -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_;
|
||||
|
70
source/fuzz/fuzzer_pass_permute_function_variables.cpp
Normal file
70
source/fuzz/fuzzer_pass_permute_function_variables.cpp
Normal 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
|
37
source/fuzz/fuzzer_pass_permute_function_variables.h
Normal file
37
source/fuzz/fuzzer_pass_permute_function_variables.h
Normal 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_
|
@ -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.
|
||||
|
@ -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>(
|
||||
|
87
source/fuzz/transformation_swap_function_variables.cpp
Normal file
87
source/fuzz/transformation_swap_function_variables.cpp
Normal 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
|
57
source/fuzz/transformation_swap_function_variables.h
Normal file
57
source/fuzz/transformation_swap_function_variables.h
Normal 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_
|
@ -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
|
||||
|
271
test/fuzz/transformation_swap_function_variables_test.cpp
Normal file
271
test/fuzz/transformation_swap_function_variables_test.cpp
Normal 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
|
@ -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(
|
||||
|
Loading…
Reference in New Issue
Block a user