spirv-fuzz: Swap positions of two functions in a module (#4236)
Adds a new transformation class that swaps the syntactic position of two functions in the module, and a fuzzer pass to apply it. Fixes #4026.
This commit is contained in:
Родитель
1b8341b8b1
Коммит
6cdf07d2b3
|
@ -121,6 +121,7 @@ if(SPIRV_BUILD_FUZZER)
|
|||
fuzzer_pass_split_blocks.h
|
||||
fuzzer_pass_swap_commutable_operands.h
|
||||
fuzzer_pass_swap_conditional_branch_operands.h
|
||||
fuzzer_pass_swap_functions.h
|
||||
fuzzer_pass_toggle_access_chain_instruction.h
|
||||
fuzzer_pass_wrap_regions_in_selections.h
|
||||
fuzzer_util.h
|
||||
|
@ -224,6 +225,7 @@ if(SPIRV_BUILD_FUZZER)
|
|||
transformation_swap_commutable_operands.h
|
||||
transformation_swap_conditional_branch_operands.h
|
||||
transformation_swap_function_variables.h
|
||||
transformation_swap_two_functions.h
|
||||
transformation_toggle_access_chain_instruction.h
|
||||
transformation_vector_shuffle.h
|
||||
transformation_wrap_early_terminator_in_function.h
|
||||
|
@ -314,6 +316,7 @@ if(SPIRV_BUILD_FUZZER)
|
|||
fuzzer_pass_split_blocks.cpp
|
||||
fuzzer_pass_swap_commutable_operands.cpp
|
||||
fuzzer_pass_swap_conditional_branch_operands.cpp
|
||||
fuzzer_pass_swap_functions.cpp
|
||||
fuzzer_pass_toggle_access_chain_instruction.cpp
|
||||
fuzzer_pass_wrap_regions_in_selections.cpp
|
||||
fuzzer_util.cpp
|
||||
|
@ -415,6 +418,7 @@ if(SPIRV_BUILD_FUZZER)
|
|||
transformation_swap_commutable_operands.cpp
|
||||
transformation_swap_conditional_branch_operands.cpp
|
||||
transformation_swap_function_variables.cpp
|
||||
transformation_swap_two_functions.cpp
|
||||
transformation_toggle_access_chain_instruction.cpp
|
||||
transformation_vector_shuffle.cpp
|
||||
transformation_wrap_early_terminator_in_function.cpp
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
#include "source/fuzz/fuzzer_pass_split_blocks.h"
|
||||
#include "source/fuzz/fuzzer_pass_swap_commutable_operands.h"
|
||||
#include "source/fuzz/fuzzer_pass_swap_conditional_branch_operands.h"
|
||||
#include "source/fuzz/fuzzer_pass_swap_functions.h"
|
||||
#include "source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h"
|
||||
#include "source/fuzz/fuzzer_pass_wrap_regions_in_selections.h"
|
||||
#include "source/fuzz/pass_management/repeated_pass_manager.h"
|
||||
|
@ -240,6 +241,7 @@ Fuzzer::Fuzzer(std::unique_ptr<opt::IRContext> ir_context,
|
|||
MaybeAddFinalPass<FuzzerPassPermuteFunctionVariables>(&final_passes_);
|
||||
MaybeAddFinalPass<FuzzerPassPermutePhiOperands>(&final_passes_);
|
||||
MaybeAddFinalPass<FuzzerPassSwapCommutableOperands>(&final_passes_);
|
||||
MaybeAddFinalPass<FuzzerPassSwapFunctions>(&final_passes_);
|
||||
MaybeAddFinalPass<FuzzerPassToggleAccessChainInstruction>(&final_passes_);
|
||||
}
|
||||
|
||||
|
|
|
@ -153,10 +153,11 @@ const std::pair<uint32_t, uint32_t> kChanceOfReplacingParametersWithGlobals = {
|
|||
const std::pair<uint32_t, uint32_t> kChanceOfReplacingParametersWithStruct = {
|
||||
20, 40};
|
||||
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> kChanceOfSwappingConditionalBranchOperands =
|
||||
{10, 70};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfSwappingFunctions = {10, 90};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfTogglingAccessChainInstruction = {
|
||||
20, 90};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfWrappingRegionInSelection = {70,
|
||||
|
@ -362,6 +363,8 @@ FuzzerContext::FuzzerContext(std::unique_ptr<RandomGenerator> random_generator,
|
|||
ChooseBetweenMinAndMax(kChanceOfSwappingAnotherPairOfFunctionVariables);
|
||||
chance_of_swapping_conditional_branch_operands_ =
|
||||
ChooseBetweenMinAndMax(kChanceOfSwappingConditionalBranchOperands);
|
||||
chance_of_swapping_functions_ =
|
||||
ChooseBetweenMinAndMax(kChanceOfSwappingFunctions);
|
||||
chance_of_toggling_access_chain_instruction_ =
|
||||
ChooseBetweenMinAndMax(kChanceOfTogglingAccessChainInstruction);
|
||||
chance_of_wrapping_region_in_selection_ =
|
||||
|
|
|
@ -369,6 +369,11 @@ class FuzzerContext {
|
|||
uint32_t GetChanceOfSwappingConditionalBranchOperands() const {
|
||||
return chance_of_swapping_conditional_branch_operands_;
|
||||
}
|
||||
|
||||
uint32_t GetChanceOfSwappingFunctions() const {
|
||||
return chance_of_swapping_functions_;
|
||||
}
|
||||
|
||||
uint32_t GetChanceOfTogglingAccessChainInstruction() const {
|
||||
return chance_of_toggling_access_chain_instruction_;
|
||||
}
|
||||
|
@ -554,6 +559,7 @@ class FuzzerContext {
|
|||
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_functions_;
|
||||
uint32_t chance_of_toggling_access_chain_instruction_;
|
||||
uint32_t chance_of_wrapping_region_in_selection_;
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
// Copyright (c) 2021 Shiyu Liu
|
||||
//
|
||||
// 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_swap_functions.h"
|
||||
|
||||
#include "source/fuzz/fuzzer_context.h"
|
||||
#include "source/fuzz/transformation_swap_two_functions.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
FuzzerPassSwapFunctions::FuzzerPassSwapFunctions(
|
||||
opt::IRContext* ir_context, TransformationContext* transformation_context,
|
||||
FuzzerContext* fuzzer_context,
|
||||
protobufs::TransformationSequence* transformations)
|
||||
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
|
||||
transformations) {}
|
||||
|
||||
void FuzzerPassSwapFunctions::Apply() {
|
||||
// Collect all function ids in a module.
|
||||
std::vector<uint32_t> function_ids;
|
||||
for (auto& function : *GetIRContext()->module()) {
|
||||
function_ids.emplace_back(function.result_id());
|
||||
}
|
||||
|
||||
size_t id_size = function_ids.size();
|
||||
// Iterate through every combination of id i & j where i!=j.
|
||||
for (size_t i = 0; i < id_size - 1; ++i) {
|
||||
for (size_t j = i + 1; j < id_size; ++j) {
|
||||
// Perform function swap randomly.
|
||||
if (!GetFuzzerContext()->ChoosePercentage(
|
||||
GetFuzzerContext()->GetChanceOfSwappingFunctions())) {
|
||||
continue;
|
||||
}
|
||||
TransformationSwapTwoFunctions transformation(function_ids[i],
|
||||
function_ids[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2021 Shiyu Liu
|
||||
//
|
||||
// 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_SWAP_FUNCTIONS_H_
|
||||
#define SOURCE_FUZZ_FUZZER_PASS_SWAP_FUNCTIONS_H_
|
||||
|
||||
#include "source/fuzz/fuzzer_pass.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
// Randomly swap functions within a module.
|
||||
class FuzzerPassSwapFunctions : public FuzzerPass {
|
||||
public:
|
||||
FuzzerPassSwapFunctions(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_SWAP_FUNCTIONS_H_
|
|
@ -1925,6 +1925,15 @@ bool NewTerminatorPreservesDominationRules(opt::IRContext* ir_context,
|
|||
return true;
|
||||
}
|
||||
|
||||
opt::Module::iterator GetFunctionIterator(opt::IRContext* ir_context,
|
||||
uint32_t function_id) {
|
||||
for (auto iter = ir_context->module()->begin();
|
||||
iter != ir_context->module()->end(); ++iter) {
|
||||
if ((*iter).result_id() == function_id) return iter;
|
||||
}
|
||||
return ir_context->module()->end();
|
||||
}
|
||||
|
||||
} // namespace fuzzerutil
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "source/opt/basic_block.h"
|
||||
#include "source/opt/instruction.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
#include "source/opt/module.h"
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
|
||||
namespace spvtools {
|
||||
|
@ -596,6 +597,12 @@ bool NewTerminatorPreservesDominationRules(opt::IRContext* ir_context,
|
|||
uint32_t block_id,
|
||||
opt::Instruction new_terminator);
|
||||
|
||||
// Return the iterator that points to the function with the corresponding
|
||||
// function id. If the function is not found, return the pointer pointing to
|
||||
// module()->end().
|
||||
opt::Module::iterator GetFunctionIterator(opt::IRContext* ir_context,
|
||||
uint32_t function_id);
|
||||
|
||||
} // namespace fuzzerutil
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
|
|
@ -558,6 +558,7 @@ message Transformation {
|
|||
TransformationMergeFunctionReturns merge_function_returns = 84;
|
||||
TransformationExpandVectorReduction expand_vector_reduction = 85;
|
||||
TransformationSwapFunctionVariables swap_function_variables = 86;
|
||||
TransformationSwapTwoFunctions swap_two_functions = 87;
|
||||
// Add additional option using the next available number.
|
||||
}
|
||||
}
|
||||
|
@ -2268,6 +2269,15 @@ message TransformationSwapFunctionVariables {
|
|||
uint32 result_id1 = 1;
|
||||
// Result id of the second variable.
|
||||
uint32 result_id2 = 2;
|
||||
|
||||
}
|
||||
|
||||
message TransformationSwapTwoFunctions {
|
||||
// A transformation that swaps the position of two functions within the same module.
|
||||
|
||||
// the IDs for the two functions that are swapped.
|
||||
uint32 function_id1 = 1;
|
||||
uint32 function_id2 = 2;
|
||||
}
|
||||
|
||||
message TransformationToggleAccessChainInstruction {
|
||||
|
|
|
@ -99,6 +99,7 @@
|
|||
#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_swap_two_functions.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"
|
||||
|
@ -365,6 +366,9 @@ std::unique_ptr<Transformation> Transformation::FromMessage(
|
|||
case protobufs::Transformation::TransformationCase::kSwapFunctionVariables:
|
||||
return MakeUnique<TransformationSwapFunctionVariables>(
|
||||
message.swap_function_variables());
|
||||
case protobufs::Transformation::TransformationCase::kSwapTwoFunctions:
|
||||
return MakeUnique<TransformationSwapTwoFunctions>(
|
||||
message.swap_two_functions());
|
||||
case protobufs::Transformation::TransformationCase::
|
||||
kToggleAccessChainInstruction:
|
||||
return MakeUnique<TransformationToggleAccessChainInstruction>(
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
// Copyright (c) 2021 Shiyu Liu
|
||||
//
|
||||
// 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_two_functions.h"
|
||||
|
||||
#include "source/opt/function.h"
|
||||
#include "source/opt/module.h"
|
||||
|
||||
#include "source/fuzz/fuzzer_util.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
TransformationSwapTwoFunctions::TransformationSwapTwoFunctions(
|
||||
protobufs::TransformationSwapTwoFunctions message)
|
||||
: message_(std::move(message)) {}
|
||||
|
||||
TransformationSwapTwoFunctions::TransformationSwapTwoFunctions(uint32_t id1,
|
||||
uint32_t id2) {
|
||||
assert(id1 != id2 && "The two function ids cannot be the same.");
|
||||
message_.set_function_id1(id1);
|
||||
message_.set_function_id2(id2);
|
||||
}
|
||||
|
||||
bool TransformationSwapTwoFunctions::IsApplicable(
|
||||
opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
|
||||
auto func1_ptr = ir_context->GetFunction(message_.function_id1());
|
||||
auto func2_ptr = ir_context->GetFunction(message_.function_id2());
|
||||
return func1_ptr != nullptr && func2_ptr != nullptr;
|
||||
}
|
||||
|
||||
void TransformationSwapTwoFunctions::Apply(
|
||||
opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
|
||||
opt::Module::iterator func1_it =
|
||||
fuzzerutil::GetFunctionIterator(ir_context, message_.function_id1());
|
||||
opt::Module::iterator func2_it =
|
||||
fuzzerutil::GetFunctionIterator(ir_context, message_.function_id2());
|
||||
|
||||
assert(func1_it != ir_context->module()->end() &&
|
||||
"Could not find function 1.");
|
||||
assert(func2_it != ir_context->module()->end() &&
|
||||
"Could not find function 2.");
|
||||
|
||||
// Two function pointers are all set, swap the two functions within the
|
||||
// module.
|
||||
std::iter_swap(func1_it.Get(), func2_it.Get());
|
||||
}
|
||||
|
||||
protobufs::Transformation TransformationSwapTwoFunctions::ToMessage() const {
|
||||
protobufs::Transformation result;
|
||||
*result.mutable_swap_two_functions() = message_;
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unordered_set<uint32_t> TransformationSwapTwoFunctions::GetFreshIds()
|
||||
const {
|
||||
return std::unordered_set<uint32_t>();
|
||||
}
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) 2021 Shiyu Liu
|
||||
//
|
||||
// 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_TWO_FUNCTIONS_H_
|
||||
#define SOURCE_FUZZ_TRANSFORMATION_SWAP_TWO_FUNCTIONS_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 {
|
||||
|
||||
class TransformationSwapTwoFunctions : public Transformation {
|
||||
public:
|
||||
explicit TransformationSwapTwoFunctions(
|
||||
protobufs::TransformationSwapTwoFunctions message);
|
||||
|
||||
TransformationSwapTwoFunctions(uint32_t function_id1, uint32_t function_id2);
|
||||
|
||||
// |function_id1| and |function_id1| should all be existing ids.
|
||||
// Swap function operation is only permitted if:
|
||||
// - both ids must be ids of functions.
|
||||
// - both ids can be found in the module.
|
||||
// - function_id1 and function_id2 are not the same.
|
||||
bool IsApplicable(
|
||||
opt::IRContext* ir_context,
|
||||
const TransformationContext& transformation_context) const override;
|
||||
|
||||
// OpFunction with |function_id1| and |function_id1| are swapped.
|
||||
void Apply(opt::IRContext* ir_context,
|
||||
TransformationContext* transformation_context) const override;
|
||||
|
||||
std::unordered_set<uint32_t> GetFreshIds() const override;
|
||||
protobufs::Transformation ToMessage() const override;
|
||||
|
||||
private:
|
||||
protobufs::TransformationSwapTwoFunctions message_;
|
||||
};
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SOURCE_FUZZ_TRANSFORMATION_SWAP_TWO_FUNCTIONS_H_
|
|
@ -115,6 +115,7 @@ if (${SPIRV_BUILD_FUZZER})
|
|||
transformation_swap_commutable_operands_test.cpp
|
||||
transformation_swap_conditional_branch_operands_test.cpp
|
||||
transformation_swap_function_variables_test.cpp
|
||||
transformation_swap_two_functions_test.cpp
|
||||
transformation_toggle_access_chain_instruction_test.cpp
|
||||
transformation_record_synonymous_constants_test.cpp
|
||||
transformation_vector_shuffle_test.cpp
|
||||
|
|
|
@ -0,0 +1,244 @@
|
|||
// Copyright (c) 2021 Shiyu Liu
|
||||
//
|
||||
// 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_two_functions.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "source/fuzz/fuzzer_util.h"
|
||||
#include "test/fuzz/fuzz_test_util.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
namespace {
|
||||
|
||||
TEST(TransformationSwapTwoFunctionsTest, SimpleTest) {
|
||||
// float multiplyBy2(in float value) {
|
||||
// return value*2.0;
|
||||
// }
|
||||
|
||||
// float multiplyBy4(in float value) {
|
||||
// return multiplyBy2(value)*2.0;
|
||||
// }
|
||||
|
||||
// float multiplyBy8(in float value) {
|
||||
// return multiplyBy2(value)*multiplyBy4(value);
|
||||
// }
|
||||
|
||||
// layout(location=0) in float value;
|
||||
// void main() { //4
|
||||
// multiplyBy2(3.7); //10
|
||||
// multiplyBy4(3.9); //13
|
||||
// multiplyBy8(5.0); //16
|
||||
// }
|
||||
|
||||
std::string shader = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %4 "main" %48
|
||||
OpExecutionMode %4 OriginUpperLeft
|
||||
OpSource ESSL 310
|
||||
OpName %4 "main"
|
||||
OpName %10 "multiplyBy2(f1;"
|
||||
OpName %9 "value"
|
||||
OpName %13 "multiplyBy4(f1;"
|
||||
OpName %12 "value"
|
||||
OpName %16 "multiplyBy8(f1;"
|
||||
OpName %15 "value"
|
||||
OpName %23 "param"
|
||||
OpName %29 "param"
|
||||
OpName %32 "param"
|
||||
OpName %39 "param"
|
||||
OpName %42 "param"
|
||||
OpName %45 "param"
|
||||
OpName %48 "value"
|
||||
OpDecorate %48 Location 0
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%6 = OpTypeFloat 32
|
||||
%7 = OpTypePointer Function %6
|
||||
%8 = OpTypeFunction %6 %7
|
||||
%19 = OpConstant %6 2
|
||||
%38 = OpConstant %6 3.70000005
|
||||
%41 = OpConstant %6 3.9000001
|
||||
%44 = OpConstant %6 5
|
||||
%47 = OpTypePointer Input %6
|
||||
%48 = OpVariable %47 Input
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
%39 = OpVariable %7 Function
|
||||
%42 = OpVariable %7 Function
|
||||
%45 = OpVariable %7 Function
|
||||
OpStore %39 %38
|
||||
%40 = OpFunctionCall %6 %10 %39
|
||||
OpStore %42 %41
|
||||
%43 = OpFunctionCall %6 %13 %42
|
||||
OpStore %45 %44
|
||||
%46 = OpFunctionCall %6 %16 %45
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%10 = OpFunction %6 None %8
|
||||
%9 = OpFunctionParameter %7
|
||||
%11 = OpLabel
|
||||
%18 = OpLoad %6 %9
|
||||
%20 = OpFMul %6 %18 %19
|
||||
OpReturnValue %20
|
||||
OpFunctionEnd
|
||||
%13 = OpFunction %6 None %8
|
||||
%12 = OpFunctionParameter %7
|
||||
%14 = OpLabel
|
||||
%23 = OpVariable %7 Function
|
||||
%24 = OpLoad %6 %12
|
||||
OpStore %23 %24
|
||||
%25 = OpFunctionCall %6 %10 %23
|
||||
%26 = OpFMul %6 %25 %19
|
||||
OpReturnValue %26
|
||||
OpFunctionEnd
|
||||
%16 = OpFunction %6 None %8
|
||||
%15 = OpFunctionParameter %7
|
||||
%17 = OpLabel
|
||||
%29 = OpVariable %7 Function
|
||||
%32 = OpVariable %7 Function
|
||||
%30 = OpLoad %6 %15
|
||||
OpStore %29 %30
|
||||
%31 = OpFunctionCall %6 %10 %29
|
||||
%33 = OpLoad %6 %15
|
||||
OpStore %32 %33
|
||||
%34 = OpFunctionCall %6 %13 %32
|
||||
%35 = OpFMul %6 %31 %34
|
||||
OpReturnValue %35
|
||||
OpFunctionEnd
|
||||
)";
|
||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||
const auto consumer = nullptr;
|
||||
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
|
||||
spvtools::ValidatorOptions validator_options;
|
||||
|
||||
// Check context validity.
|
||||
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
||||
kConsoleMessageConsumer));
|
||||
|
||||
TransformationContext transformation_context(
|
||||
MakeUnique<FactManager>(context.get()), validator_options);
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Function should not swap with itself.
|
||||
ASSERT_DEATH(TransformationSwapTwoFunctions(4, 4).IsApplicable(
|
||||
context.get(), transformation_context),
|
||||
"The two function ids cannot be the same.");
|
||||
#endif
|
||||
|
||||
// Function with id 29 does not exist.
|
||||
ASSERT_FALSE(TransformationSwapTwoFunctions(10, 29).IsApplicable(
|
||||
context.get(), transformation_context));
|
||||
|
||||
// Function with id 30 does not exist.
|
||||
ASSERT_FALSE(TransformationSwapTwoFunctions(30, 13).IsApplicable(
|
||||
context.get(), transformation_context));
|
||||
|
||||
// Both functions with id 5 and 6 do not exist.
|
||||
ASSERT_FALSE(TransformationSwapTwoFunctions(5, 6).IsApplicable(
|
||||
context.get(), transformation_context));
|
||||
|
||||
// Function with result_id 10 and 13 should swap successfully.
|
||||
auto swap_test5 = TransformationSwapTwoFunctions(10, 13);
|
||||
ASSERT_TRUE(swap_test5.IsApplicable(context.get(), transformation_context));
|
||||
ApplyAndCheckFreshIds(swap_test5, 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" %48
|
||||
OpExecutionMode %4 OriginUpperLeft
|
||||
OpSource ESSL 310
|
||||
OpName %4 "main"
|
||||
OpName %10 "multiplyBy2(f1;"
|
||||
OpName %9 "value"
|
||||
OpName %13 "multiplyBy4(f1;"
|
||||
OpName %12 "value"
|
||||
OpName %16 "multiplyBy8(f1;"
|
||||
OpName %15 "value"
|
||||
OpName %23 "param"
|
||||
OpName %29 "param"
|
||||
OpName %32 "param"
|
||||
OpName %39 "param"
|
||||
OpName %42 "param"
|
||||
OpName %45 "param"
|
||||
OpName %48 "value"
|
||||
OpDecorate %48 Location 0
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%6 = OpTypeFloat 32
|
||||
%7 = OpTypePointer Function %6
|
||||
%8 = OpTypeFunction %6 %7
|
||||
%19 = OpConstant %6 2
|
||||
%38 = OpConstant %6 3.70000005
|
||||
%41 = OpConstant %6 3.9000001
|
||||
%44 = OpConstant %6 5
|
||||
%47 = OpTypePointer Input %6
|
||||
%48 = OpVariable %47 Input
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
%39 = OpVariable %7 Function
|
||||
%42 = OpVariable %7 Function
|
||||
%45 = OpVariable %7 Function
|
||||
OpStore %39 %38
|
||||
%40 = OpFunctionCall %6 %10 %39
|
||||
OpStore %42 %41
|
||||
%43 = OpFunctionCall %6 %13 %42
|
||||
OpStore %45 %44
|
||||
%46 = OpFunctionCall %6 %16 %45
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%13 = OpFunction %6 None %8
|
||||
%12 = OpFunctionParameter %7
|
||||
%14 = OpLabel
|
||||
%23 = OpVariable %7 Function
|
||||
%24 = OpLoad %6 %12
|
||||
OpStore %23 %24
|
||||
%25 = OpFunctionCall %6 %10 %23
|
||||
%26 = OpFMul %6 %25 %19
|
||||
OpReturnValue %26
|
||||
OpFunctionEnd
|
||||
%10 = OpFunction %6 None %8
|
||||
%9 = OpFunctionParameter %7
|
||||
%11 = OpLabel
|
||||
%18 = OpLoad %6 %9
|
||||
%20 = OpFMul %6 %18 %19
|
||||
OpReturnValue %20
|
||||
OpFunctionEnd
|
||||
%16 = OpFunction %6 None %8
|
||||
%15 = OpFunctionParameter %7
|
||||
%17 = OpLabel
|
||||
%29 = OpVariable %7 Function
|
||||
%32 = OpVariable %7 Function
|
||||
%30 = OpLoad %6 %15
|
||||
OpStore %29 %30
|
||||
%31 = OpFunctionCall %6 %10 %29
|
||||
%33 = OpLoad %6 %15
|
||||
OpStore %32 %33
|
||||
%34 = OpFunctionCall %6 %13 %32
|
||||
%35 = OpFMul %6 %31 %34
|
||||
OpReturnValue %35
|
||||
OpFunctionEnd
|
||||
)";
|
||||
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
|
@ -38,7 +38,8 @@ AUTHORS = ['The Khronos Group Inc.',
|
|||
'Advanced Micro Devices, Inc.',
|
||||
'Stefano Milizia',
|
||||
'Alastair F. Donaldson',
|
||||
'Mostafa Ashraf']
|
||||
'Mostafa Ashraf',
|
||||
'Shiyu Liu']
|
||||
CURRENT_YEAR='2021'
|
||||
|
||||
YEARS = '(2014-2016|2015-2016|2015-2020|2016|2016-2017|2017|2017-2019|2018|2019|2020|2021)'
|
||||
|
|
Загрузка…
Ссылка в новой задаче