#include "source/fuzz/fuzzer_pass_add_local_variables.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/transformation_add_local_variable.h"
#include "source/fuzz/transformation_add_type_pointer.h"
namespace spvtools {
namespace fuzz {
FuzzerPassAddLocalVariables::FuzzerPassAddLocalVariables(
opt::IRContext* ir_context, TransformationContext* transformation_context,
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations,
bool ignore_inapplicable_transformations)
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations, ignore_inapplicable_transformations) {}
void FuzzerPassAddLocalVariables::Apply() {
auto basic_type_ids_and_pointers =
GetAvailableBasicTypesAndPointers(spv::StorageClass::Function);
auto& basic_types = basic_type_ids_and_pointers.first;
if (basic_types.empty()) {
return;
}
auto& basic_type_to_pointers = basic_type_ids_and_pointers.second;
for (auto& function : *GetIRContext()->module()) {
while (GetFuzzerContext()->ChoosePercentage(
GetFuzzerContext()->GetChanceOfAddingLocalVariable())) {
uint32_t basic_type =
basic_types[GetFuzzerContext()->RandomIndex(basic_types)];
uint32_t pointer_type;
std::vector<uint32_t>& available_pointers_to_basic_type =
basic_type_to_pointers.at(basic_type);
if (available_pointers_to_basic_type.empty()) {
pointer_type = GetFuzzerContext()->GetFreshId();
ApplyTransformation(TransformationAddTypePointer(
pointer_type, spv::StorageClass::Function, basic_type));
available_pointers_to_basic_type.push_back(pointer_type);
} else {
pointer_type =
available_pointers_to_basic_type[GetFuzzerContext()->RandomIndex(
available_pointers_to_basic_type)];
}
ApplyTransformation(TransformationAddLocalVariable(
GetFuzzerContext()->GetFreshId(), pointer_type, function.result_id(),
FindOrCreateZeroConstant(basic_type, false), true));
}
}
}
}
}