Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spirv-fuzz: adds TransformationReplaceCopyObjectWithStoreLoad #3567

Merged
29 changes: 14 additions & 15 deletions source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,20 @@ FuzzerPassReplaceCopyObjectsWithStoresLoads::

void FuzzerPassReplaceCopyObjectsWithStoresLoads::Apply() {
GetIRContext()->module()->ForEachInst([this](opt::Instruction* instruction) {
// Randomly decide whether to replace OpCopyObject.
if (!GetFuzzerContext()->ChoosePercentage(
GetFuzzerContext()
->GetChanceOfReplacingCopyObjectWithStoreLoad())) {
return;
}
// The instruction must be OpCopyObject.
if (instruction->opcode() != SpvOpCopyObject) return;
if (instruction->opcode() != SpvOpCopyObject) {
return;
}
// The |type_id()| of the instruction cannot be a pointer,
if (instruction->type_id() == SpvOpTypePointer) return;

if (instruction->type_id() == SpvOpTypePointer) {
return;
}
// It must be valid to insert OpStore and OpLoad instructions
// before the instruction OpCopyObject.
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpStore,
Expand All @@ -48,28 +57,18 @@ void FuzzerPassReplaceCopyObjectsWithStoresLoads::Apply() {
return;
}

// Randomly decide whether to replace OpCopyObject.
if (!GetFuzzerContext()->ChoosePercentage(
GetFuzzerContext()
->GetChanceOfReplacingCopyObjectWithStoreLoad())) {
return;
}

// Randomly decides whether a global or local variable will be added.
auto variable_storage_class = GetFuzzerContext()->ChooseEven()
? SpvStorageClassPrivate
: SpvStorageClassFunction;

// Find or create a constant to initialize the variable from. This might
// update module's id bound so it must be done before any fresh ids are
// computed.

// Find or create a constant to initialize the variable from.
auto variable_initializer_id =
FindOrCreateZeroConstant(instruction->type_id());

// Make sure that pointer type is defined.
FindOrCreatePointerType(instruction->type_id(), variable_storage_class);
// Applies the transformation replacing OpCopyObject with Store and Load.
// Apply the transformation replacing OpCopyObject with Store and Load.
ApplyTransformation(TransformationReplaceCopyObjectWithStoreLoad(
instruction->result_id(), GetFuzzerContext()->GetFreshId(),
variable_storage_class, variable_initializer_id));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@

#include "source/fuzz/fuzzer_pass.h"

namespace spvtools {
namespace fuzz {
antonikarp marked this conversation as resolved.
Show resolved Hide resolved
// Replaces instructions OpCopyObject with storing into a new variable
// and immediately loading this variable to |result_id| of the
// original OpCopyObject instruction.

namespace spvtools {
namespace fuzz {

class FuzzerPassReplaceCopyObjectsWithStoresLoads : public FuzzerPass {
public:
FuzzerPassReplaceCopyObjectsWithStoresLoads(
Expand Down
8 changes: 4 additions & 4 deletions source/fuzz/protobufs/spvtoolsfuzz.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1278,19 +1278,19 @@ message TransformationReplaceConstantWithUniform {
message TransformationReplaceCopyObjectWithStoreLoad {

// A transformation that replaces instruction OpCopyObject with
// storing into a new variable and immediately loading this
// storing into a new variable and immediately loading from this
// variable to |result_id| of the original OpCopyObject instruction.

// The result id of initial OpCopyLoad instruction
// The result id of initial OpCopyObject instruction
uint32 copy_object_result_id = 1;

// A fresh id for the variable to be stored to.
uint32 fresh_variable_id = 2;

// The variable storage class (local or global).
// The variable storage class (Function or Private).
uint32 variable_storage_class = 3;

// Constant to initialize the variable from.
// Constant to initialize the variable with.
uint32 variable_initializer_id = 4;
}

Expand Down
17 changes: 12 additions & 5 deletions source/fuzz/transformation_replace_copy_object_with_store_load.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,15 @@ bool TransformationReplaceCopyObjectWithStoreLoad::IsApplicable(
ir_context->get_def_use_mgr()->GetDef(message_.copy_object_result_id());

// This must be a defined OpCopyObject instruction.
if ((!copy_object_instruction) ||
(copy_object_instruction->opcode() != SpvOpCopyObject))
if (!copy_object_instruction ||
copy_object_instruction->opcode() != SpvOpCopyObject) {
return false;
antonikarp marked this conversation as resolved.
Show resolved Hide resolved
}
// The |type_id()| of the instruction cannot be a pointer,
// because we cannot define a pointer to pointer
if (copy_object_instruction->type_id() == SpvOpTypePointer) return false;
if (copy_object_instruction->type_id() == SpvOpTypePointer) {
return false;
}

// It must be valid to insert the OpStore and OpLoad instruction before it.
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpStore,
Expand All @@ -77,15 +80,19 @@ bool TransformationReplaceCopyObjectWithStoreLoad::IsApplicable(
return false;
}
// |message_.variable_storage_class| must be Private or Function.
return ((message_.variable_storage_class() == SpvStorageClassPrivate ||
message_.variable_storage_class() == SpvStorageClassFunction));
return (message_.variable_storage_class() == SpvStorageClassPrivate ||
message_.variable_storage_class() == SpvStorageClassFunction);
antonikarp marked this conversation as resolved.
Show resolved Hide resolved
}

void TransformationReplaceCopyObjectWithStoreLoad::Apply(
opt::IRContext* ir_context,
TransformationContext* transformation_context) const {
auto copy_object_instruction =
ir_context->get_def_use_mgr()->GetDef(message_.copy_object_result_id());
// |copy_object_instruction| must be defined.
assert(copy_object_instruction &&
copy_object_instruction->opcode() == SpvOpCopyObject &&
"The required OpCopyObject instruction must be defined.");
// Get id used as a source by the OpCopyObject instruction.
uint32_t src_operand = copy_object_instruction->GetSingleWordOperand(2);
// A pointer type instruction pointing to the value type must be defined.
Expand Down
15 changes: 7 additions & 8 deletions source/fuzz/transformation_replace_copy_object_with_store_load.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,22 @@ class TransformationReplaceCopyObjectWithStoreLoad : public Transformation {
uint32_t copy_object_result_id, uint32_t fresh_variable_id,
uint32_t variable_storage_class, uint32_t variable_initializer_id);

// - |message_.copy_object_result_id| must be a result id of an instruction
// OpStoreLoad.
// - |message_.copy_object_result_id| must be a result id of an OpCopyObject
// instruction.
// - |message_.fresh_variable_id| must be a fresh id given to variable used by
// OpStore
// OpStore.
// - |message_.variable_storage_class| must be either StorageClassPrivate or
// StorageClassFunction
// StorageClassFunction.
// - |message_.initializer_id| must be a result id of some constant in the
// module. Its type must be equal to the pointee type of the variable that
// will be created.

bool IsApplicable(
opt::IRContext* ir_context,
const TransformationContext& transformation_context) const override;

// Replaces instruction OpCopyObject with
// storing into a new variable and immediately loading this
// variable to |result_id| of the original OpCopyObject instruction.
// Replaces instruction OpCopyObject with storing into a new variable and
// immediately loading from this variable to |result_id| of the original
// OpCopyObject instruction.
void Apply(opt::IRContext* ir_context,
TransformationContext* transformation_context) const override;

Expand Down