mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-25 04:50:04 +00:00
spirv-fuzz: Add fuzzer pass to permute function parameters (#3212)
Fixes #3194.
This commit is contained in:
parent
da4cd21485
commit
533af49812
3
.gitignore
vendored
3
.gitignore
vendored
@ -29,3 +29,6 @@ bazel-testlogs
|
||||
# C-Lion
|
||||
/.idea/
|
||||
/cmake-build-*/
|
||||
|
||||
# VSCode
|
||||
/.vscode/*
|
||||
|
@ -62,6 +62,7 @@ if(SPIRV_BUILD_FUZZER)
|
||||
fuzzer_pass_obfuscate_constants.h
|
||||
fuzzer_pass_outline_functions.h
|
||||
fuzzer_pass_permute_blocks.h
|
||||
fuzzer_pass_permute_function_parameters.h
|
||||
fuzzer_pass_split_blocks.h
|
||||
fuzzer_pass_swap_commutable_operands.h
|
||||
fuzzer_util.h
|
||||
@ -104,6 +105,7 @@ if(SPIRV_BUILD_FUZZER)
|
||||
transformation_merge_blocks.h
|
||||
transformation_move_block_down.h
|
||||
transformation_outline_function.h
|
||||
transformation_permute_function_parameters.h
|
||||
transformation_replace_boolean_constant_with_constant_binary.h
|
||||
transformation_replace_constant_with_uniform.h
|
||||
transformation_replace_id_with_synonym.h
|
||||
@ -150,6 +152,7 @@ if(SPIRV_BUILD_FUZZER)
|
||||
fuzzer_pass_obfuscate_constants.cpp
|
||||
fuzzer_pass_outline_functions.cpp
|
||||
fuzzer_pass_permute_blocks.cpp
|
||||
fuzzer_pass_permute_function_parameters.cpp
|
||||
fuzzer_pass_split_blocks.cpp
|
||||
fuzzer_pass_swap_commutable_operands.cpp
|
||||
fuzzer_util.cpp
|
||||
@ -191,6 +194,7 @@ if(SPIRV_BUILD_FUZZER)
|
||||
transformation_merge_blocks.cpp
|
||||
transformation_move_block_down.cpp
|
||||
transformation_outline_function.cpp
|
||||
transformation_permute_function_parameters.cpp
|
||||
transformation_replace_boolean_constant_with_constant_binary.cpp
|
||||
transformation_replace_constant_with_uniform.cpp
|
||||
transformation_replace_id_with_synonym.cpp
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "source/fuzz/fuzzer_pass_obfuscate_constants.h"
|
||||
#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_split_blocks.h"
|
||||
#include "source/fuzz/fuzzer_pass_swap_commutable_operands.h"
|
||||
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
|
||||
@ -244,6 +245,9 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run(
|
||||
MaybeAddPass<FuzzerPassPermuteBlocks>(&passes, ir_context.get(),
|
||||
&fact_manager, &fuzzer_context,
|
||||
transformation_sequence_out);
|
||||
MaybeAddPass<FuzzerPassPermuteFunctionParameters>(
|
||||
&passes, ir_context.get(), &fact_manager, &fuzzer_context,
|
||||
transformation_sequence_out);
|
||||
MaybeAddPass<FuzzerPassSplitBlocks>(&passes, ir_context.get(),
|
||||
&fact_manager, &fuzzer_context,
|
||||
transformation_sequence_out);
|
||||
|
@ -60,6 +60,7 @@ const std::pair<uint32_t, uint32_t> kChanceOfMergingBlocks = {20, 95};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfMovingBlockDown = {20, 50};
|
||||
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> kChanceOfPermutingParameters = {30, 90};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfReplacingIdWithSynonym = {10, 90};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfSplittingBlock = {40, 95};
|
||||
|
||||
@ -146,6 +147,8 @@ FuzzerContext::FuzzerContext(RandomGenerator* random_generator,
|
||||
ChooseBetweenMinAndMax(kChanceOfObfuscatingConstant);
|
||||
chance_of_outlining_function_ =
|
||||
ChooseBetweenMinAndMax(kChanceOfOutliningFunction);
|
||||
chance_of_permuting_parameters_ =
|
||||
ChooseBetweenMinAndMax(kChanceOfPermutingParameters);
|
||||
chance_of_replacing_id_with_synonym_ =
|
||||
ChooseBetweenMinAndMax(kChanceOfReplacingIdWithSynonym);
|
||||
chance_of_splitting_block_ = ChooseBetweenMinAndMax(kChanceOfSplittingBlock);
|
||||
|
@ -62,6 +62,40 @@ class FuzzerContext {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Randomly shuffles a |sequence| between |lo| and |hi| indices inclusively.
|
||||
// |lo| and |hi| must be valid indices to the |sequence|
|
||||
template <typename T>
|
||||
void Shuffle(std::vector<T>* sequence, size_t lo, size_t hi) const {
|
||||
auto& array = *sequence;
|
||||
|
||||
if (array.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(lo <= hi && hi < array.size() && "lo and/or hi indices are invalid");
|
||||
|
||||
// i > lo to account for potential infinite loop when lo == 0
|
||||
for (size_t i = hi; i > lo; --i) {
|
||||
auto index =
|
||||
random_generator_->RandomUint32(static_cast<uint32_t>(i - lo + 1));
|
||||
|
||||
if (lo + index != i) {
|
||||
// Introduce std::swap to the scope but don't use it
|
||||
// directly since there might be a better overload
|
||||
using std::swap;
|
||||
swap(array[lo + index], array[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ramdomly shuffles a |sequence|
|
||||
template <typename T>
|
||||
void Shuffle(std::vector<T>* sequence) const {
|
||||
if (!sequence->empty()) {
|
||||
Shuffle(sequence, 0, sequence->size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Yields an id that is guaranteed not to be used in the module being fuzzed,
|
||||
// or to have been issued before.
|
||||
uint32_t GetFreshId();
|
||||
@ -139,6 +173,9 @@ class FuzzerContext {
|
||||
uint32_t GetChanceOfOutliningFunction() {
|
||||
return chance_of_outlining_function_;
|
||||
}
|
||||
uint32_t GetChanceOfPermutingParameters() {
|
||||
return chance_of_permuting_parameters_;
|
||||
}
|
||||
uint32_t GetChanceOfReplacingIdWithSynonym() {
|
||||
return chance_of_replacing_id_with_synonym_;
|
||||
}
|
||||
@ -203,6 +240,7 @@ class FuzzerContext {
|
||||
uint32_t chance_of_moving_block_down_;
|
||||
uint32_t chance_of_obfuscating_constant_;
|
||||
uint32_t chance_of_outlining_function_;
|
||||
uint32_t chance_of_permuting_parameters_;
|
||||
uint32_t chance_of_replacing_id_with_synonym_;
|
||||
uint32_t chance_of_splitting_block_;
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "source/fuzz/transformation_add_global_undef.h"
|
||||
#include "source/fuzz/transformation_add_type_boolean.h"
|
||||
#include "source/fuzz/transformation_add_type_float.h"
|
||||
#include "source/fuzz/transformation_add_type_function.h"
|
||||
#include "source/fuzz/transformation_add_type_int.h"
|
||||
#include "source/fuzz/transformation_add_type_matrix.h"
|
||||
#include "source/fuzz/transformation_add_type_pointer.h"
|
||||
@ -179,6 +180,26 @@ uint32_t FuzzerPass::FindOrCreate32BitFloatType() {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t FuzzerPass::FindOrCreateFunctionType(
|
||||
uint32_t return_type_id, const std::vector<uint32_t>& argument_id) {
|
||||
// FindFunctionType has a sigle argument for OpTypeFunction operands
|
||||
// so we will have to copy them all in this vector
|
||||
std::vector<uint32_t> type_ids(argument_id.size() + 1);
|
||||
type_ids[0] = return_type_id;
|
||||
std::copy(argument_id.begin(), argument_id.end(), type_ids.begin() + 1);
|
||||
|
||||
// Check if type exists
|
||||
auto existing_id = fuzzerutil::FindFunctionType(GetIRContext(), type_ids);
|
||||
if (existing_id) {
|
||||
return existing_id;
|
||||
}
|
||||
|
||||
auto result = GetFuzzerContext()->GetFreshId();
|
||||
ApplyTransformation(
|
||||
TransformationAddTypeFunction(result, return_type_id, argument_id));
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t FuzzerPass::FindOrCreateVectorType(uint32_t component_type_id,
|
||||
uint32_t component_count) {
|
||||
assert(component_count >= 2 && component_count <= 4 &&
|
||||
|
@ -112,6 +112,12 @@ class FuzzerPass {
|
||||
// instruction does not exist, a transformation is applied to add it.
|
||||
uint32_t FindOrCreate32BitFloatType();
|
||||
|
||||
// Returns the id of an OpTypeFunction %<return_type_id> %<...argument_id>
|
||||
// instruction. If such an instruction doesn't exist, a transformation
|
||||
// is applied to create a new one.
|
||||
uint32_t FindOrCreateFunctionType(uint32_t return_type_id,
|
||||
const std::vector<uint32_t>& argument_id);
|
||||
|
||||
// Returns the id of an OpTypeVector instruction, with |component_type_id|
|
||||
// (which must already exist) as its base type, and |component_count|
|
||||
// elements (which must be in the range [2, 4]). If such an instruction does
|
||||
|
81
source/fuzz/fuzzer_pass_permute_function_parameters.cpp
Normal file
81
source/fuzz/fuzzer_pass_permute_function_parameters.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2020 Vasyl Teliman
|
||||
//
|
||||
// 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 <numeric>
|
||||
#include <vector>
|
||||
|
||||
#include "source/fuzz/fuzzer_context.h"
|
||||
#include "source/fuzz/fuzzer_pass_permute_function_parameters.h"
|
||||
#include "source/fuzz/fuzzer_util.h"
|
||||
#include "source/fuzz/instruction_descriptor.h"
|
||||
#include "source/fuzz/transformation_permute_function_parameters.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
FuzzerPassPermuteFunctionParameters::FuzzerPassPermuteFunctionParameters(
|
||||
opt::IRContext* ir_context, FactManager* fact_manager,
|
||||
FuzzerContext* fuzzer_context,
|
||||
protobufs::TransformationSequence* transformations)
|
||||
: FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
|
||||
|
||||
FuzzerPassPermuteFunctionParameters::~FuzzerPassPermuteFunctionParameters() =
|
||||
default;
|
||||
|
||||
void FuzzerPassPermuteFunctionParameters::Apply() {
|
||||
for (const auto& function : *GetIRContext()->module()) {
|
||||
uint32_t function_id = function.result_id();
|
||||
|
||||
// Skip the function if it is an entry point
|
||||
if (fuzzerutil::FunctionIsEntryPoint(GetIRContext(), function_id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!GetFuzzerContext()->ChoosePercentage(
|
||||
GetFuzzerContext()->GetChanceOfPermutingParameters())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compute permutation for parameters
|
||||
auto* function_type =
|
||||
fuzzerutil::GetFunctionType(GetIRContext(), &function);
|
||||
assert(function_type && "Function type is null");
|
||||
|
||||
// Don't take return type into account
|
||||
uint32_t arg_size = function_type->NumInOperands() - 1;
|
||||
|
||||
// Create a vector, fill it with [0, n-1] values and shuffle it
|
||||
std::vector<uint32_t> permutation(arg_size);
|
||||
std::iota(permutation.begin(), permutation.end(), 0);
|
||||
GetFuzzerContext()->Shuffle(&permutation);
|
||||
|
||||
// Create a new OpFunctionType instruction with permuted arguments
|
||||
// if needed
|
||||
auto result_type_id = function_type->GetSingleWordInOperand(0);
|
||||
std::vector<uint32_t> argument_ids;
|
||||
|
||||
for (auto index : permutation) {
|
||||
// +1 to take function's return type into account
|
||||
argument_ids.push_back(function_type->GetSingleWordInOperand(index + 1));
|
||||
}
|
||||
|
||||
// Apply our transformation
|
||||
ApplyTransformation(TransformationPermuteFunctionParameters(
|
||||
function_id, FindOrCreateFunctionType(result_type_id, argument_ids),
|
||||
permutation));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
45
source/fuzz/fuzzer_pass_permute_function_parameters.h
Normal file
45
source/fuzz/fuzzer_pass_permute_function_parameters.h
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2020 Vasyl Teliman
|
||||
//
|
||||
// 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_PARAMETERS_H_
|
||||
#define SOURCE_FUZZ_FUZZER_PASS_PERMUTE_FUNCTION_PARAMETERS_H_
|
||||
|
||||
#include "source/fuzz/fuzzer_pass.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
// Fuzzer pass that, given a non-entry-point function taking n parameters
|
||||
// and a permutation of the set [0, n - 1]:
|
||||
// 1. Introduces a new function type that is the same as the original
|
||||
// function's type but with the order of arguments permuted
|
||||
// (only add this if it doesn't already exist)
|
||||
// 2. Changes the type of the function to this type
|
||||
// 3. Adjusts all calls to the function so that their arguments are permuted
|
||||
class FuzzerPassPermuteFunctionParameters : public FuzzerPass {
|
||||
public:
|
||||
FuzzerPassPermuteFunctionParameters(
|
||||
opt::IRContext* ir_context, FactManager* fact_manager,
|
||||
FuzzerContext* fuzzer_context,
|
||||
protobufs::TransformationSequence* transformations);
|
||||
|
||||
~FuzzerPassPermuteFunctionParameters();
|
||||
|
||||
void Apply() override;
|
||||
};
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SOURCE_FUZZ_FUZZER_PASS_PERMUTE_FUNCTION_PARAMETERS_H_
|
@ -395,6 +395,12 @@ uint32_t FindFunctionType(opt::IRContext* ir_context,
|
||||
return 0;
|
||||
}
|
||||
|
||||
opt::Instruction* GetFunctionType(opt::IRContext* context,
|
||||
const opt::Function* function) {
|
||||
uint32_t type_id = function->DefInst().GetSingleWordInOperand(1);
|
||||
return context->get_def_use_mgr()->GetDef(type_id);
|
||||
}
|
||||
|
||||
opt::Function* FindFunction(opt::IRContext* ir_context, uint32_t function_id) {
|
||||
for (auto& function : *ir_context->module()) {
|
||||
if (function.result_id() == function_id) {
|
||||
@ -404,6 +410,15 @@ opt::Function* FindFunction(opt::IRContext* ir_context, uint32_t function_id) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool FunctionIsEntryPoint(opt::IRContext* context, uint32_t function_id) {
|
||||
for (auto& entry_point : context->module()->entry_points()) {
|
||||
if (entry_point.GetSingleWordInOperand(1) == function_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IdIsAvailableAtUse(opt::IRContext* context,
|
||||
opt::Instruction* use_instruction,
|
||||
uint32_t use_input_operand_index, uint32_t id) {
|
||||
|
@ -152,10 +152,20 @@ bool IsMergeOrContinue(opt::IRContext* ir_context, uint32_t block_id);
|
||||
uint32_t FindFunctionType(opt::IRContext* ir_context,
|
||||
const std::vector<uint32_t>& type_ids);
|
||||
|
||||
// Returns a type instruction (OpTypeFunction) for |function|.
|
||||
// Returns |nullptr| if type is not found.
|
||||
opt::Instruction* GetFunctionType(opt::IRContext* context,
|
||||
const opt::Function* function);
|
||||
|
||||
// Returns the function with result id |function_id|, or |nullptr| if no such
|
||||
// function exists.
|
||||
opt::Function* FindFunction(opt::IRContext* ir_context, uint32_t function_id);
|
||||
|
||||
// Returns |true| if one of entry points has function id |function_id|.
|
||||
// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3218):
|
||||
// TransformationAddFunctionCall also has this functionality as a static method
|
||||
bool FunctionIsEntryPoint(opt::IRContext* context, uint32_t function_id);
|
||||
|
||||
// Checks whether |id| is available (according to dominance rules) at the use
|
||||
// point defined by input operand |use_input_operand_index| of
|
||||
// |use_instruction|.
|
||||
|
@ -370,6 +370,7 @@ message Transformation {
|
||||
TransformationAccessChain access_chain = 39;
|
||||
TransformationEquationInstruction equation_instruction = 40;
|
||||
TransformationSwapCommutableOperands swap_commutable_operands = 41;
|
||||
TransformationPermuteFunctionParameters permute_function_parameters = 42;
|
||||
// Add additional option using the next available number.
|
||||
}
|
||||
}
|
||||
@ -907,6 +908,36 @@ message TransformationOutlineFunction {
|
||||
|
||||
}
|
||||
|
||||
message TransformationPermuteFunctionParameters {
|
||||
|
||||
// A transformation that, given a non-entry-point function taking n
|
||||
// parameters and a permutation of the set [0, n-1]:
|
||||
// - Introduces a new function type that is the same as the original
|
||||
// function's type but with the order of arguments permuted
|
||||
// (only if it doesn't already exist)
|
||||
// - Changes the type of the function to this type
|
||||
// - Adjusts all calls to the function so that their arguments are permuted
|
||||
|
||||
// Function, whose parameters will be permuted
|
||||
uint32 function_id = 1;
|
||||
|
||||
// |new_type_id| is a result id of a valid OpTypeFunction instruction.
|
||||
// New type is valid if:
|
||||
// - it has the same number of operands as the old one
|
||||
// - function's result type is the same as the old one
|
||||
// - function's arguments are permuted according to |permutation| vector
|
||||
uint32 new_type_id = 2;
|
||||
|
||||
// An array of size |n|, where |n| is a number of arguments to a function
|
||||
// with |function_id|. For each i: 0 <= permutation[i] < n.
|
||||
//
|
||||
// i-th element of this array contains a position for an i-th
|
||||
// function's argument (i.e. i-th argument will be permutation[i]-th
|
||||
// after running this transformation)
|
||||
repeated uint32 permutation = 3;
|
||||
|
||||
}
|
||||
|
||||
message TransformationReplaceBooleanConstantWithConstantBinary {
|
||||
|
||||
// A transformation to capture replacing a use of a boolean constant with
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "source/fuzz/transformation_merge_blocks.h"
|
||||
#include "source/fuzz/transformation_move_block_down.h"
|
||||
#include "source/fuzz/transformation_outline_function.h"
|
||||
#include "source/fuzz/transformation_permute_function_parameters.h"
|
||||
#include "source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h"
|
||||
#include "source/fuzz/transformation_replace_constant_with_uniform.h"
|
||||
#include "source/fuzz/transformation_replace_id_with_synonym.h"
|
||||
@ -144,6 +145,10 @@ std::unique_ptr<Transformation> Transformation::FromMessage(
|
||||
case protobufs::Transformation::TransformationCase::kOutlineFunction:
|
||||
return MakeUnique<TransformationOutlineFunction>(
|
||||
message.outline_function());
|
||||
case protobufs::Transformation::TransformationCase::
|
||||
kPermuteFunctionParameters:
|
||||
return MakeUnique<TransformationPermuteFunctionParameters>(
|
||||
message.permute_function_parameters());
|
||||
case protobufs::Transformation::TransformationCase::
|
||||
kReplaceBooleanConstantWithConstantBinary:
|
||||
return MakeUnique<TransformationReplaceBooleanConstantWithConstantBinary>(
|
||||
|
@ -37,7 +37,7 @@ class TransformationAddTypeFunction : public Transformation {
|
||||
// - |message_.return_type_id| and each element of |message_.argument_type_id|
|
||||
// must be the ids of non-function types
|
||||
// - The module must not contain an OpTypeFunction instruction defining a
|
||||
// function type with the signature provided by teh given return and
|
||||
// function type with the signature provided by the given return and
|
||||
// argument types
|
||||
bool IsApplicable(opt::IRContext* context,
|
||||
const FactManager& fact_manager) const override;
|
||||
|
184
source/fuzz/transformation_permute_function_parameters.cpp
Normal file
184
source/fuzz/transformation_permute_function_parameters.cpp
Normal file
@ -0,0 +1,184 @@
|
||||
// Copyright (c) 2020 Vasyl Teliman
|
||||
//
|
||||
// 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 <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "source/fuzz/fuzzer_util.h"
|
||||
#include "source/fuzz/transformation_permute_function_parameters.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
TransformationPermuteFunctionParameters::
|
||||
TransformationPermuteFunctionParameters(
|
||||
const spvtools::fuzz::protobufs::
|
||||
TransformationPermuteFunctionParameters& message)
|
||||
: message_(message) {}
|
||||
|
||||
TransformationPermuteFunctionParameters::
|
||||
TransformationPermuteFunctionParameters(
|
||||
uint32_t function_id, uint32_t new_type_id,
|
||||
const std::vector<uint32_t>& permutation) {
|
||||
message_.set_function_id(function_id);
|
||||
message_.set_new_type_id(new_type_id);
|
||||
|
||||
for (auto index : permutation) {
|
||||
message_.add_permutation(index);
|
||||
}
|
||||
}
|
||||
|
||||
bool TransformationPermuteFunctionParameters::IsApplicable(
|
||||
opt::IRContext* context, const FactManager& /*unused*/) const {
|
||||
// Check that function exists
|
||||
const auto* function =
|
||||
fuzzerutil::FindFunction(context, message_.function_id());
|
||||
if (!function || function->DefInst().opcode() != SpvOpFunction ||
|
||||
fuzzerutil::FunctionIsEntryPoint(context, function->result_id())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that permutation has valid indices
|
||||
const auto* function_type = fuzzerutil::GetFunctionType(context, function);
|
||||
assert(function_type && "Function type is null");
|
||||
|
||||
const auto& permutation = message_.permutation();
|
||||
|
||||
// Don't take return type into account
|
||||
auto arg_size = function_type->NumInOperands() - 1;
|
||||
|
||||
// |permutation| vector should be equal to the number of arguments
|
||||
if (static_cast<uint32_t>(permutation.size()) != arg_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that all indices are valid
|
||||
// and unique integers from the [0, n-1] set
|
||||
std::unordered_set<uint32_t> unique_indices;
|
||||
for (auto index : permutation) {
|
||||
// We don't compare |index| with 0 since it's an unsigned integer
|
||||
if (index >= arg_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unique_indices.insert(index);
|
||||
}
|
||||
|
||||
// Check that permutation doesn't have duplicated values
|
||||
assert(unique_indices.size() == arg_size && "Permutation has duplicates");
|
||||
|
||||
// Check that new function's type is valid:
|
||||
// - Has the same number of operands
|
||||
// - Has the same result type as the old one
|
||||
// - Order of arguments is permuted
|
||||
auto new_type_id = message_.new_type_id();
|
||||
const auto* new_type = context->get_def_use_mgr()->GetDef(new_type_id);
|
||||
|
||||
if (!new_type || new_type->opcode() != SpvOpTypeFunction ||
|
||||
new_type->NumInOperands() != function_type->NumInOperands()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that both instructions have the same result type
|
||||
if (new_type->GetSingleWordInOperand(0) !=
|
||||
function_type->GetSingleWordInOperand(0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that new function type has its arguments permuted
|
||||
for (int i = 0, n = static_cast<int>(permutation.size()); i < n; ++i) {
|
||||
// +1 to take return type into account
|
||||
if (new_type->GetSingleWordInOperand(i + 1) !=
|
||||
function_type->GetSingleWordInOperand(permutation[i] + 1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TransformationPermuteFunctionParameters::Apply(
|
||||
opt::IRContext* context, FactManager* /*unused*/) const {
|
||||
// Retrieve all data from the message
|
||||
uint32_t function_id = message_.function_id();
|
||||
uint32_t new_type_id = message_.new_type_id();
|
||||
const auto& permutation = message_.permutation();
|
||||
|
||||
// Find the function that will be transformed
|
||||
auto* function = fuzzerutil::FindFunction(context, function_id);
|
||||
assert(function && "Can't find the function");
|
||||
|
||||
// Change function's type
|
||||
function->DefInst().SetInOperand(1, {new_type_id});
|
||||
|
||||
// Adjust OpFunctionParameter instructions
|
||||
|
||||
// Collect ids and types from OpFunctionParameter instructions
|
||||
std::vector<uint32_t> param_id, param_type;
|
||||
function->ForEachParam(
|
||||
[¶m_id, ¶m_type](const opt::Instruction* param) {
|
||||
param_id.push_back(param->result_id());
|
||||
param_type.push_back(param->type_id());
|
||||
});
|
||||
|
||||
// Permute parameters' ids and types
|
||||
std::vector<uint32_t> permuted_param_id, permuted_param_type;
|
||||
for (auto index : permutation) {
|
||||
permuted_param_id.push_back(param_id[index]);
|
||||
permuted_param_type.push_back(param_type[index]);
|
||||
}
|
||||
|
||||
// Set OpFunctionParameter instructions to point to new parameters
|
||||
size_t i = 0;
|
||||
function->ForEachParam(
|
||||
[&i, &permuted_param_id, &permuted_param_type](opt::Instruction* param) {
|
||||
param->SetResultType(permuted_param_type[i]);
|
||||
param->SetResultId(permuted_param_id[i]);
|
||||
++i;
|
||||
});
|
||||
|
||||
// Fix all OpFunctionCall instructions
|
||||
context->get_def_use_mgr()->ForEachUser(
|
||||
&function->DefInst(),
|
||||
[function_id, &permutation](opt::Instruction* call) {
|
||||
if (call->opcode() != SpvOpFunctionCall ||
|
||||
call->GetSingleWordInOperand(0) != function_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
opt::Instruction::OperandList call_operands = {
|
||||
call->GetInOperand(0) // Function id
|
||||
};
|
||||
|
||||
for (auto index : permutation) {
|
||||
// Take function id into account
|
||||
call_operands.push_back(call->GetInOperand(index + 1));
|
||||
}
|
||||
|
||||
call->SetInOperands(std::move(call_operands));
|
||||
});
|
||||
|
||||
// Make sure our changes are analyzed
|
||||
context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
|
||||
}
|
||||
|
||||
protobufs::Transformation TransformationPermuteFunctionParameters::ToMessage()
|
||||
const {
|
||||
protobufs::Transformation result;
|
||||
*result.mutable_permute_function_parameters() = message_;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
61
source/fuzz/transformation_permute_function_parameters.h
Normal file
61
source/fuzz/transformation_permute_function_parameters.h
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright (c) 2020 Vasyl Teliman
|
||||
//
|
||||
// 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_PERMUTE_FUNCTION_PARAMETERS_H_
|
||||
#define SOURCE_FUZZ_TRANSFORMATION_PERMUTE_FUNCTION_PARAMETERS_H_
|
||||
|
||||
#include "source/fuzz/fact_manager.h"
|
||||
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
|
||||
#include "source/fuzz/transformation.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
class TransformationPermuteFunctionParameters : public Transformation {
|
||||
public:
|
||||
explicit TransformationPermuteFunctionParameters(
|
||||
const protobufs::TransformationPermuteFunctionParameters& message);
|
||||
|
||||
TransformationPermuteFunctionParameters(
|
||||
uint32_t function_id, uint32_t new_type_id,
|
||||
const std::vector<uint32_t>& permutation);
|
||||
|
||||
// - |function_id| is a valid non-entry-point OpFunction instruction
|
||||
// - |new_type_id| is a result id of a valid OpTypeFunction instruction.
|
||||
// New type is valid if:
|
||||
// - it has the same number of operands as the old one
|
||||
// - function's result type is the same as the old one
|
||||
// - function's arguments are permuted according to |permutation| vector
|
||||
// - |permutation| is a set of [0..(n - 1)], where n is a number of arguments
|
||||
// to the function
|
||||
bool IsApplicable(opt::IRContext* context,
|
||||
const FactManager& fact_manager) const override;
|
||||
|
||||
// - OpFunction instruction with |result_id == function_id| is changed.
|
||||
// Its arguments are permuted according to the |permutation| vector
|
||||
// - Changed function gets a new type specified by |type_id|
|
||||
// - Calls to the function are adjusted accordingly
|
||||
void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
|
||||
|
||||
protobufs::Transformation ToMessage() const override;
|
||||
|
||||
private:
|
||||
protobufs::TransformationPermuteFunctionParameters message_;
|
||||
};
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SOURCE_FUZZ_TRANSFORMATION_PERMUTE_FUNCTION_PARAMETERS_H_
|
@ -54,6 +54,7 @@ if (${SPIRV_BUILD_FUZZER})
|
||||
transformation_merge_blocks_test.cpp
|
||||
transformation_move_block_down_test.cpp
|
||||
transformation_outline_function_test.cpp
|
||||
transformation_permute_function_parameters_test.cpp
|
||||
transformation_replace_boolean_constant_with_constant_binary_test.cpp
|
||||
transformation_replace_constant_with_uniform_test.cpp
|
||||
transformation_replace_id_with_synonym_test.cpp
|
||||
|
430
test/fuzz/transformation_permute_function_parameters_test.cpp
Normal file
430
test/fuzz/transformation_permute_function_parameters_test.cpp
Normal file
@ -0,0 +1,430 @@
|
||||
// Copyright (c) 2020 Vasyl Teliman
|
||||
//
|
||||
// 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_permute_function_parameters.h"
|
||||
#include "test/fuzz/fuzz_test_util.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
namespace {
|
||||
|
||||
TEST(TransformationPermuteFunctionParametersTest, BasicTest) {
|
||||
std::string shader = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %4 "main" %72 %74
|
||||
OpExecutionMode %4 OriginUpperLeft
|
||||
OpSource ESSL 310
|
||||
OpName %4 "main"
|
||||
OpName %12 "g(f1;f1;"
|
||||
OpName %10 "x"
|
||||
OpName %11 "y"
|
||||
OpName %22 "f(f1;i1;vf2;"
|
||||
OpName %19 "x"
|
||||
OpName %20 "y"
|
||||
OpName %21 "z"
|
||||
OpName %28 "cond(i1;f1;"
|
||||
OpName %26 "a"
|
||||
OpName %27 "b"
|
||||
OpName %53 "param"
|
||||
OpName %54 "param"
|
||||
OpName %66 "param"
|
||||
OpName %67 "param"
|
||||
OpName %72 "color"
|
||||
OpName %74 "gl_FragCoord"
|
||||
OpName %75 "param"
|
||||
OpName %79 "param"
|
||||
OpName %85 "param"
|
||||
OpName %86 "param"
|
||||
OpName %91 "param"
|
||||
OpName %92 "param"
|
||||
OpName %93 "param"
|
||||
OpName %99 "param"
|
||||
OpName %100 "param"
|
||||
OpName %101 "param"
|
||||
OpDecorate %20 RelaxedPrecision
|
||||
OpDecorate %26 RelaxedPrecision
|
||||
OpDecorate %47 RelaxedPrecision
|
||||
OpDecorate %58 RelaxedPrecision
|
||||
OpDecorate %72 Location 0
|
||||
OpDecorate %74 BuiltIn FragCoord
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%6 = OpTypeFloat 32
|
||||
%7 = OpTypePointer Function %6
|
||||
%8 = OpTypeVector %6 4
|
||||
%9 = OpTypeFunction %8 %7 %7
|
||||
%14 = OpTypeInt 32 1
|
||||
%15 = OpTypePointer Function %14
|
||||
%16 = OpTypeVector %6 2
|
||||
%17 = OpTypePointer Function %16
|
||||
%18 = OpTypeFunction %8 %7 %15 %17
|
||||
%24 = OpTypeBool
|
||||
%25 = OpTypeFunction %24 %15 %7
|
||||
%105 = OpTypeFunction %24 %7 %15 ; predefined type for %28
|
||||
%31 = OpConstant %6 255
|
||||
%33 = OpConstant %6 0
|
||||
%34 = OpConstant %6 1
|
||||
%42 = OpTypeInt 32 0
|
||||
%43 = OpConstant %42 0
|
||||
%49 = OpConstant %42 1
|
||||
%64 = OpConstant %14 4
|
||||
%65 = OpConstant %6 5
|
||||
%71 = OpTypePointer Output %8
|
||||
%72 = OpVariable %71 Output
|
||||
%73 = OpTypePointer Input %8
|
||||
%74 = OpVariable %73 Input
|
||||
%76 = OpTypePointer Input %6
|
||||
%84 = OpConstant %14 5
|
||||
%90 = OpConstant %6 3
|
||||
%98 = OpConstant %6 4
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
%66 = OpVariable %15 Function
|
||||
%67 = OpVariable %7 Function
|
||||
%75 = OpVariable %7 Function
|
||||
%79 = OpVariable %7 Function
|
||||
%85 = OpVariable %15 Function
|
||||
%86 = OpVariable %7 Function
|
||||
%91 = OpVariable %7 Function
|
||||
%92 = OpVariable %15 Function
|
||||
%93 = OpVariable %17 Function
|
||||
%99 = OpVariable %7 Function
|
||||
%100 = OpVariable %15 Function
|
||||
%101 = OpVariable %17 Function
|
||||
OpStore %66 %64
|
||||
OpStore %67 %65
|
||||
%68 = OpFunctionCall %24 %28 %66 %67
|
||||
OpSelectionMerge %70 None
|
||||
OpBranchConditional %68 %69 %83
|
||||
%69 = OpLabel
|
||||
%77 = OpAccessChain %76 %74 %43
|
||||
%78 = OpLoad %6 %77
|
||||
OpStore %75 %78
|
||||
%80 = OpAccessChain %76 %74 %49
|
||||
%81 = OpLoad %6 %80
|
||||
OpStore %79 %81
|
||||
%82 = OpFunctionCall %8 %12 %75 %79
|
||||
OpStore %72 %82
|
||||
OpBranch %70
|
||||
%83 = OpLabel
|
||||
OpStore %85 %84
|
||||
OpStore %86 %65
|
||||
%87 = OpFunctionCall %24 %28 %85 %86
|
||||
OpSelectionMerge %89 None
|
||||
OpBranchConditional %87 %88 %97
|
||||
%88 = OpLabel
|
||||
OpStore %91 %90
|
||||
OpStore %92 %64
|
||||
%94 = OpLoad %8 %74
|
||||
%95 = OpVectorShuffle %16 %94 %94 0 1
|
||||
OpStore %93 %95
|
||||
%96 = OpFunctionCall %8 %22 %91 %92 %93
|
||||
OpStore %72 %96
|
||||
OpBranch %89
|
||||
%97 = OpLabel
|
||||
OpStore %99 %98
|
||||
OpStore %100 %84
|
||||
%102 = OpLoad %8 %74
|
||||
%103 = OpVectorShuffle %16 %102 %102 0 1
|
||||
OpStore %101 %103
|
||||
%104 = OpFunctionCall %8 %22 %99 %100 %101
|
||||
OpStore %72 %104
|
||||
OpBranch %89
|
||||
%89 = OpLabel
|
||||
OpBranch %70
|
||||
%70 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%12 = OpFunction %8 None %9
|
||||
%10 = OpFunctionParameter %7
|
||||
%11 = OpFunctionParameter %7
|
||||
%13 = OpLabel
|
||||
%30 = OpLoad %6 %10
|
||||
%32 = OpFDiv %6 %30 %31
|
||||
%35 = OpLoad %6 %11
|
||||
%36 = OpFDiv %6 %35 %31
|
||||
%37 = OpFSub %6 %34 %36
|
||||
%38 = OpCompositeConstruct %8 %32 %33 %37 %34
|
||||
OpReturnValue %38
|
||||
OpFunctionEnd
|
||||
%22 = OpFunction %8 None %18
|
||||
%19 = OpFunctionParameter %7
|
||||
%20 = OpFunctionParameter %15
|
||||
%21 = OpFunctionParameter %17
|
||||
%23 = OpLabel
|
||||
%53 = OpVariable %7 Function
|
||||
%54 = OpVariable %7 Function
|
||||
%41 = OpLoad %6 %19
|
||||
%44 = OpAccessChain %7 %21 %43
|
||||
%45 = OpLoad %6 %44
|
||||
%46 = OpFAdd %6 %41 %45
|
||||
%47 = OpLoad %14 %20
|
||||
%48 = OpConvertSToF %6 %47
|
||||
%50 = OpAccessChain %7 %21 %49
|
||||
%51 = OpLoad %6 %50
|
||||
%52 = OpFAdd %6 %48 %51
|
||||
OpStore %53 %46
|
||||
OpStore %54 %52
|
||||
%55 = OpFunctionCall %8 %12 %53 %54
|
||||
OpReturnValue %55
|
||||
OpFunctionEnd
|
||||
%28 = OpFunction %24 None %25
|
||||
%26 = OpFunctionParameter %15
|
||||
%27 = OpFunctionParameter %7
|
||||
%29 = OpLabel
|
||||
%58 = OpLoad %14 %26
|
||||
%59 = OpConvertSToF %6 %58
|
||||
%60 = OpLoad %6 %27
|
||||
%61 = OpFOrdLessThan %24 %59 %60
|
||||
OpReturnValue %61
|
||||
OpFunctionEnd
|
||||
|
||||
)";
|
||||
|
||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||
const auto consumer = nullptr;
|
||||
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
FactManager fact_manager;
|
||||
|
||||
// Can't permute main function
|
||||
ASSERT_FALSE(TransformationPermuteFunctionParameters(4, 0, {}).IsApplicable(
|
||||
context.get(), fact_manager));
|
||||
|
||||
// Can't permute invalid instruction
|
||||
ASSERT_FALSE(TransformationPermuteFunctionParameters(101, 0, {})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
// Permutation has too many values
|
||||
ASSERT_FALSE(TransformationPermuteFunctionParameters(22, 0, {2, 1, 0, 3})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
// Permutation has too few values
|
||||
ASSERT_FALSE(TransformationPermuteFunctionParameters(22, 0, {0, 1})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
// Permutation has invalid values
|
||||
ASSERT_FALSE(TransformationPermuteFunctionParameters(22, 0, {3, 1, 0})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
// Type id is not an OpTypeFunction instruction
|
||||
ASSERT_FALSE(TransformationPermuteFunctionParameters(22, 42, {2, 1, 0})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
// Type id has incorrect number of operands
|
||||
ASSERT_FALSE(TransformationPermuteFunctionParameters(22, 9, {2, 1, 0})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
// OpTypeFunction has operands out of order
|
||||
ASSERT_FALSE(TransformationPermuteFunctionParameters(22, 18, {2, 1, 0})
|
||||
.IsApplicable(context.get(), fact_manager));
|
||||
|
||||
// Successful transformations
|
||||
{
|
||||
// Function has two operands of the same type:
|
||||
// initial OpTypeFunction should be enough
|
||||
TransformationPermuteFunctionParameters transformation(12, 9, {1, 0});
|
||||
ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
|
||||
transformation.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
}
|
||||
{
|
||||
TransformationPermuteFunctionParameters transformation(28, 105, {1, 0});
|
||||
ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
|
||||
transformation.Apply(context.get(), &fact_manager);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
}
|
||||
|
||||
std::string after_transformation = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %4 "main" %72 %74
|
||||
OpExecutionMode %4 OriginUpperLeft
|
||||
OpSource ESSL 310
|
||||
OpName %4 "main"
|
||||
OpName %12 "g(f1;f1;"
|
||||
OpName %10 "x"
|
||||
OpName %11 "y"
|
||||
OpName %22 "f(f1;i1;vf2;"
|
||||
OpName %19 "x"
|
||||
OpName %20 "y"
|
||||
OpName %21 "z"
|
||||
OpName %28 "cond(i1;f1;"
|
||||
OpName %26 "a"
|
||||
OpName %27 "b"
|
||||
OpName %53 "param"
|
||||
OpName %54 "param"
|
||||
OpName %66 "param"
|
||||
OpName %67 "param"
|
||||
OpName %72 "color"
|
||||
OpName %74 "gl_FragCoord"
|
||||
OpName %75 "param"
|
||||
OpName %79 "param"
|
||||
OpName %85 "param"
|
||||
OpName %86 "param"
|
||||
OpName %91 "param"
|
||||
OpName %92 "param"
|
||||
OpName %93 "param"
|
||||
OpName %99 "param"
|
||||
OpName %100 "param"
|
||||
OpName %101 "param"
|
||||
OpDecorate %20 RelaxedPrecision
|
||||
OpDecorate %26 RelaxedPrecision
|
||||
OpDecorate %47 RelaxedPrecision
|
||||
OpDecorate %58 RelaxedPrecision
|
||||
OpDecorate %72 Location 0
|
||||
OpDecorate %74 BuiltIn FragCoord
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%6 = OpTypeFloat 32
|
||||
%7 = OpTypePointer Function %6
|
||||
%8 = OpTypeVector %6 4
|
||||
%9 = OpTypeFunction %8 %7 %7
|
||||
%14 = OpTypeInt 32 1
|
||||
%15 = OpTypePointer Function %14
|
||||
%16 = OpTypeVector %6 2
|
||||
%17 = OpTypePointer Function %16
|
||||
%18 = OpTypeFunction %8 %7 %15 %17
|
||||
%24 = OpTypeBool
|
||||
%25 = OpTypeFunction %24 %15 %7
|
||||
%105 = OpTypeFunction %24 %7 %15 ; predefined type for %28
|
||||
%31 = OpConstant %6 255
|
||||
%33 = OpConstant %6 0
|
||||
%34 = OpConstant %6 1
|
||||
%42 = OpTypeInt 32 0
|
||||
%43 = OpConstant %42 0
|
||||
%49 = OpConstant %42 1
|
||||
%64 = OpConstant %14 4
|
||||
%65 = OpConstant %6 5
|
||||
%71 = OpTypePointer Output %8
|
||||
%72 = OpVariable %71 Output
|
||||
%73 = OpTypePointer Input %8
|
||||
%74 = OpVariable %73 Input
|
||||
%76 = OpTypePointer Input %6
|
||||
%84 = OpConstant %14 5
|
||||
%90 = OpConstant %6 3
|
||||
%98 = OpConstant %6 4
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
%66 = OpVariable %15 Function
|
||||
%67 = OpVariable %7 Function
|
||||
%75 = OpVariable %7 Function
|
||||
%79 = OpVariable %7 Function
|
||||
%85 = OpVariable %15 Function
|
||||
%86 = OpVariable %7 Function
|
||||
%91 = OpVariable %7 Function
|
||||
%92 = OpVariable %15 Function
|
||||
%93 = OpVariable %17 Function
|
||||
%99 = OpVariable %7 Function
|
||||
%100 = OpVariable %15 Function
|
||||
%101 = OpVariable %17 Function
|
||||
OpStore %66 %64
|
||||
OpStore %67 %65
|
||||
%68 = OpFunctionCall %24 %28 %67 %66
|
||||
OpSelectionMerge %70 None
|
||||
OpBranchConditional %68 %69 %83
|
||||
%69 = OpLabel
|
||||
%77 = OpAccessChain %76 %74 %43
|
||||
%78 = OpLoad %6 %77
|
||||
OpStore %75 %78
|
||||
%80 = OpAccessChain %76 %74 %49
|
||||
%81 = OpLoad %6 %80
|
||||
OpStore %79 %81
|
||||
%82 = OpFunctionCall %8 %12 %79 %75
|
||||
OpStore %72 %82
|
||||
OpBranch %70
|
||||
%83 = OpLabel
|
||||
OpStore %85 %84
|
||||
OpStore %86 %65
|
||||
%87 = OpFunctionCall %24 %28 %86 %85
|
||||
OpSelectionMerge %89 None
|
||||
OpBranchConditional %87 %88 %97
|
||||
%88 = OpLabel
|
||||
OpStore %91 %90
|
||||
OpStore %92 %64
|
||||
%94 = OpLoad %8 %74
|
||||
%95 = OpVectorShuffle %16 %94 %94 0 1
|
||||
OpStore %93 %95
|
||||
%96 = OpFunctionCall %8 %22 %91 %92 %93
|
||||
OpStore %72 %96
|
||||
OpBranch %89
|
||||
%97 = OpLabel
|
||||
OpStore %99 %98
|
||||
OpStore %100 %84
|
||||
%102 = OpLoad %8 %74
|
||||
%103 = OpVectorShuffle %16 %102 %102 0 1
|
||||
OpStore %101 %103
|
||||
%104 = OpFunctionCall %8 %22 %99 %100 %101
|
||||
OpStore %72 %104
|
||||
OpBranch %89
|
||||
%89 = OpLabel
|
||||
OpBranch %70
|
||||
%70 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%12 = OpFunction %8 None %9
|
||||
%11 = OpFunctionParameter %7
|
||||
%10 = OpFunctionParameter %7
|
||||
%13 = OpLabel
|
||||
%30 = OpLoad %6 %10
|
||||
%32 = OpFDiv %6 %30 %31
|
||||
%35 = OpLoad %6 %11
|
||||
%36 = OpFDiv %6 %35 %31
|
||||
%37 = OpFSub %6 %34 %36
|
||||
%38 = OpCompositeConstruct %8 %32 %33 %37 %34
|
||||
OpReturnValue %38
|
||||
OpFunctionEnd
|
||||
%22 = OpFunction %8 None %18
|
||||
%19 = OpFunctionParameter %7
|
||||
%20 = OpFunctionParameter %15
|
||||
%21 = OpFunctionParameter %17
|
||||
%23 = OpLabel
|
||||
%53 = OpVariable %7 Function
|
||||
%54 = OpVariable %7 Function
|
||||
%41 = OpLoad %6 %19
|
||||
%44 = OpAccessChain %7 %21 %43
|
||||
%45 = OpLoad %6 %44
|
||||
%46 = OpFAdd %6 %41 %45
|
||||
%47 = OpLoad %14 %20
|
||||
%48 = OpConvertSToF %6 %47
|
||||
%50 = OpAccessChain %7 %21 %49
|
||||
%51 = OpLoad %6 %50
|
||||
%52 = OpFAdd %6 %48 %51
|
||||
OpStore %53 %46
|
||||
OpStore %54 %52
|
||||
%55 = OpFunctionCall %8 %12 %54 %53
|
||||
OpReturnValue %55
|
||||
OpFunctionEnd
|
||||
%28 = OpFunction %24 None %105
|
||||
%27 = OpFunctionParameter %7
|
||||
%26 = OpFunctionParameter %15
|
||||
%29 = OpLabel
|
||||
%58 = OpLoad %14 %26
|
||||
%59 = OpConvertSToF %6 %58
|
||||
%60 = OpLoad %6 %27
|
||||
%61 = OpFOrdLessThan %24 %59 %60
|
||||
OpReturnValue %61
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
@ -33,7 +33,8 @@ AUTHORS = ['The Khronos Group Inc.',
|
||||
'Google LLC',
|
||||
'Pierre Moreau',
|
||||
'Samsung Inc',
|
||||
'André Perez Maselco']
|
||||
'André Perez Maselco',
|
||||
'Vasyl Teliman']
|
||||
CURRENT_YEAR='2020'
|
||||
|
||||
YEARS = '(2014-2016|2015-2016|2016|2016-2017|2017|2017-2019|2018|2019|2020)'
|
||||
|
Loading…
Reference in New Issue
Block a user