mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-23 04:00:05 +00:00
parent
12a4fb3bc1
commit
9494703546
@ -49,6 +49,7 @@ if(SPIRV_BUILD_FUZZER)
|
||||
fuzzer_pass_add_local_variables.h
|
||||
fuzzer_pass_add_no_contraction_decorations.h
|
||||
fuzzer_pass_add_stores.h
|
||||
fuzzer_pass_add_vector_shuffle_instructions.h
|
||||
fuzzer_pass_adjust_branch_weights.h
|
||||
fuzzer_pass_adjust_function_controls.h
|
||||
fuzzer_pass_adjust_loop_controls.h
|
||||
@ -150,6 +151,7 @@ if(SPIRV_BUILD_FUZZER)
|
||||
fuzzer_pass_add_local_variables.cpp
|
||||
fuzzer_pass_add_no_contraction_decorations.cpp
|
||||
fuzzer_pass_add_stores.cpp
|
||||
fuzzer_pass_add_vector_shuffle_instructions.cpp
|
||||
fuzzer_pass_adjust_branch_weights.cpp
|
||||
fuzzer_pass_adjust_function_controls.cpp
|
||||
fuzzer_pass_adjust_loop_controls.cpp
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "source/fuzz/fuzzer_pass_add_local_variables.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_no_contraction_decorations.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_stores.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.h"
|
||||
#include "source/fuzz/fuzzer_pass_adjust_branch_weights.h"
|
||||
#include "source/fuzz/fuzzer_pass_adjust_function_controls.h"
|
||||
#include "source/fuzz/fuzzer_pass_adjust_loop_controls.h"
|
||||
@ -224,6 +225,9 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run(
|
||||
MaybeAddPass<FuzzerPassAddStores>(&passes, ir_context.get(),
|
||||
&transformation_context, &fuzzer_context,
|
||||
transformation_sequence_out);
|
||||
MaybeAddPass<FuzzerPassAddVectorShuffleInstructions>(
|
||||
&passes, ir_context.get(), &transformation_context, &fuzzer_context,
|
||||
transformation_sequence_out);
|
||||
MaybeAddPass<FuzzerPassApplyIdSynonyms>(
|
||||
&passes, ir_context.get(), &transformation_context, &fuzzer_context,
|
||||
transformation_sequence_out);
|
||||
|
@ -40,6 +40,7 @@ const std::pair<uint32_t, uint32_t> kChanceOfAddingNoContractionDecoration = {
|
||||
5, 70};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfAddingStore = {5, 50};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfAddingVectorType = {20, 70};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfAddingVectorShuffle = {20, 70};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfAdjustingBranchWeights = {20, 90};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfAdjustingFunctionControl = {20,
|
||||
70};
|
||||
@ -126,6 +127,8 @@ FuzzerContext::FuzzerContext(RandomGenerator* random_generator,
|
||||
chance_of_adding_no_contraction_decoration_ =
|
||||
ChooseBetweenMinAndMax(kChanceOfAddingNoContractionDecoration);
|
||||
chance_of_adding_store_ = ChooseBetweenMinAndMax(kChanceOfAddingStore);
|
||||
chance_of_adding_vector_shuffle_ =
|
||||
ChooseBetweenMinAndMax(kChanceOfAddingVectorShuffle);
|
||||
chance_of_adding_vector_type_ =
|
||||
ChooseBetweenMinAndMax(kChanceOfAddingVectorType);
|
||||
chance_of_adjusting_branch_weights_ =
|
||||
|
@ -136,6 +136,9 @@ class FuzzerContext {
|
||||
return chance_of_adding_no_contraction_decoration_;
|
||||
}
|
||||
uint32_t GetChanceOfAddingStore() { return chance_of_adding_store_; }
|
||||
uint32_t GetChanceOfAddingVectorShuffle() {
|
||||
return chance_of_adding_vector_shuffle_;
|
||||
}
|
||||
uint32_t GetChanceOfAddingVectorType() {
|
||||
return chance_of_adding_vector_type_;
|
||||
}
|
||||
@ -201,18 +204,6 @@ class FuzzerContext {
|
||||
uint32_t GetMaximumEquivalenceClassSizeForDataSynonymFactClosure() {
|
||||
return max_equivalence_class_size_for_data_synonym_fact_closure_;
|
||||
}
|
||||
uint32_t GetRandomIndexForAccessChain(uint32_t composite_size_bound) {
|
||||
return random_generator_->RandomUint32(composite_size_bound);
|
||||
}
|
||||
uint32_t GetRandomLoopControlPartialCount() {
|
||||
return random_generator_->RandomUint32(max_loop_control_partial_count_);
|
||||
}
|
||||
uint32_t GetRandomLoopControlPeelCount() {
|
||||
return random_generator_->RandomUint32(max_loop_control_peel_count_);
|
||||
}
|
||||
uint32_t GetRandomLoopLimit() {
|
||||
return random_generator_->RandomUint32(max_loop_limit_);
|
||||
}
|
||||
std::pair<uint32_t, uint32_t> GetRandomBranchWeights() {
|
||||
std::pair<uint32_t, uint32_t> branch_weights = {0, 0};
|
||||
|
||||
@ -225,6 +216,29 @@ class FuzzerContext {
|
||||
|
||||
return branch_weights;
|
||||
}
|
||||
std::vector<uint32_t> GetRandomComponentsForVectorShuffle(
|
||||
uint32_t max_component_index) {
|
||||
// Component count must be in range [2, 4].
|
||||
std::vector<uint32_t> components(random_generator_->RandomUint32(2) + 2);
|
||||
|
||||
for (uint32_t& component : components) {
|
||||
component = random_generator_->RandomUint32(max_component_index);
|
||||
}
|
||||
|
||||
return components;
|
||||
}
|
||||
uint32_t GetRandomIndexForAccessChain(uint32_t composite_size_bound) {
|
||||
return random_generator_->RandomUint32(composite_size_bound);
|
||||
}
|
||||
uint32_t GetRandomLoopControlPartialCount() {
|
||||
return random_generator_->RandomUint32(max_loop_control_partial_count_);
|
||||
}
|
||||
uint32_t GetRandomLoopControlPeelCount() {
|
||||
return random_generator_->RandomUint32(max_loop_control_peel_count_);
|
||||
}
|
||||
uint32_t GetRandomLoopLimit() {
|
||||
return random_generator_->RandomUint32(max_loop_limit_);
|
||||
}
|
||||
uint32_t GetRandomSizeForNewArray() {
|
||||
// Ensure that the array size is non-zero.
|
||||
return random_generator_->RandomUint32(max_new_array_size_limit_ - 1) + 1;
|
||||
@ -254,6 +268,7 @@ class FuzzerContext {
|
||||
uint32_t chance_of_adding_matrix_type_;
|
||||
uint32_t chance_of_adding_no_contraction_decoration_;
|
||||
uint32_t chance_of_adding_store_;
|
||||
uint32_t chance_of_adding_vector_shuffle_;
|
||||
uint32_t chance_of_adding_vector_type_;
|
||||
uint32_t chance_of_adjusting_branch_weights_;
|
||||
uint32_t chance_of_adjusting_function_control_;
|
||||
|
133
source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp
Normal file
133
source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
// Copyright (c) 2020 André Perez Maselco
|
||||
//
|
||||
// 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_add_vector_shuffle_instructions.h"
|
||||
|
||||
#include "source/fuzz/fuzzer_util.h"
|
||||
#include "source/fuzz/instruction_descriptor.h"
|
||||
#include "source/fuzz/transformation_vector_shuffle.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
FuzzerPassAddVectorShuffleInstructions::FuzzerPassAddVectorShuffleInstructions(
|
||||
opt::IRContext* ir_context, TransformationContext* transformation_context,
|
||||
FuzzerContext* fuzzer_context,
|
||||
protobufs::TransformationSequence* transformations)
|
||||
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
|
||||
transformations) {}
|
||||
|
||||
FuzzerPassAddVectorShuffleInstructions::
|
||||
~FuzzerPassAddVectorShuffleInstructions() = default;
|
||||
|
||||
void FuzzerPassAddVectorShuffleInstructions::Apply() {
|
||||
ForEachInstructionWithInstructionDescriptor(
|
||||
[this](opt::Function* function, opt::BasicBlock* block,
|
||||
opt::BasicBlock::iterator instruction_iterator,
|
||||
const protobufs::InstructionDescriptor& instruction_descriptor)
|
||||
-> void {
|
||||
assert(instruction_iterator->opcode() ==
|
||||
instruction_descriptor.target_instruction_opcode() &&
|
||||
"The opcode of the instruction we might insert before must be "
|
||||
"the same as the opcode in the descriptor for the instruction");
|
||||
|
||||
// Randomly decide whether to try adding an OpVectorShuffle instruction.
|
||||
if (!GetFuzzerContext()->ChoosePercentage(
|
||||
GetFuzzerContext()->GetChanceOfAddingVectorShuffle())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// It must be valid to insert an OpVectorShuffle instruction
|
||||
// before |instruction_iterator|.
|
||||
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
|
||||
SpvOpVectorShuffle, instruction_iterator)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Looks for vectors that we might consider to use as OpVectorShuffle
|
||||
// operands.
|
||||
std::vector<opt::Instruction*> vector_instructions =
|
||||
FindAvailableInstructions(
|
||||
function, block, instruction_iterator,
|
||||
[instruction_descriptor](
|
||||
opt::IRContext* ir_context,
|
||||
opt::Instruction* instruction) -> bool {
|
||||
if (!instruction->type_id()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ir_context->get_type_mgr()
|
||||
->GetType(instruction->type_id())
|
||||
->AsVector()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return fuzzerutil::IdIsAvailableBeforeInstruction(
|
||||
ir_context,
|
||||
FindInstruction(instruction_descriptor, ir_context),
|
||||
instruction->result_id());
|
||||
});
|
||||
|
||||
// If there are no vector instructions, then return.
|
||||
if (vector_instructions.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto vector_1_instruction =
|
||||
vector_instructions[GetFuzzerContext()->RandomIndex(
|
||||
vector_instructions)];
|
||||
auto vector_1_type = GetIRContext()
|
||||
->get_type_mgr()
|
||||
->GetType(vector_1_instruction->type_id())
|
||||
->AsVector();
|
||||
|
||||
auto vector_2_instruction =
|
||||
GetFuzzerContext()->RemoveAtRandomIndex(&vector_instructions);
|
||||
auto vector_2_type = GetIRContext()
|
||||
->get_type_mgr()
|
||||
->GetType(vector_2_instruction->type_id())
|
||||
->AsVector();
|
||||
|
||||
// |vector_1| and |vector_2| must have the same element type as each
|
||||
// other. The loop is guaranteed to terminate because each iteration
|
||||
// removes on possible choice for |vector_2|, and there is at least one
|
||||
// choice that will cause the loop to exit - namely |vector_1|.
|
||||
while (vector_1_type->element_type() != vector_2_type->element_type()) {
|
||||
vector_2_instruction =
|
||||
GetFuzzerContext()->RemoveAtRandomIndex(&vector_instructions);
|
||||
vector_2_type = GetIRContext()
|
||||
->get_type_mgr()
|
||||
->GetType(vector_2_instruction->type_id())
|
||||
->AsVector();
|
||||
}
|
||||
|
||||
// Gets components and creates the appropriate result vector type.
|
||||
std::vector<uint32_t> components =
|
||||
GetFuzzerContext()->GetRandomComponentsForVectorShuffle(
|
||||
vector_1_type->element_count() +
|
||||
vector_2_type->element_count());
|
||||
FindOrCreateVectorType(GetIRContext()->get_type_mgr()->GetId(
|
||||
vector_1_type->element_type()),
|
||||
static_cast<uint32_t>(components.size()));
|
||||
|
||||
// Applies the vector shuffle transformation.
|
||||
ApplyTransformation(TransformationVectorShuffle(
|
||||
instruction_descriptor, GetFuzzerContext()->GetFreshId(),
|
||||
vector_1_instruction->result_id(),
|
||||
vector_2_instruction->result_id(), components));
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
39
source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.h
Normal file
39
source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.h
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2020 André Perez Maselco
|
||||
//
|
||||
// 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_ADD_VECTOR_SHUFFLE_INSTRUCTIONS_H_
|
||||
#define SOURCE_FUZZ_FUZZER_PASS_ADD_VECTOR_SHUFFLE_INSTRUCTIONS_H_
|
||||
|
||||
#include "source/fuzz/fuzzer_pass.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
// Adds OpVectorShuffle instructions to the module.
|
||||
class FuzzerPassAddVectorShuffleInstructions : public FuzzerPass {
|
||||
public:
|
||||
FuzzerPassAddVectorShuffleInstructions(
|
||||
opt::IRContext* ir_context, TransformationContext* transformation_context,
|
||||
FuzzerContext* fuzzer_context,
|
||||
protobufs::TransformationSequence* transformations);
|
||||
|
||||
~FuzzerPassAddVectorShuffleInstructions();
|
||||
|
||||
void Apply() override;
|
||||
};
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SOURCE_FUZZ_FUZZER_PASS_ADD_VECTOR_SHUFFLE_INSTRUCTIONS_H_
|
Loading…
Reference in New Issue
Block a user