mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-23 04:00:05 +00:00
parent
fba90d6b0a
commit
4a92579a45
@ -28,6 +28,7 @@
|
||||
#include "source/fuzz/transformation_add_type_int.h"
|
||||
#include "source/fuzz/transformation_add_type_matrix.h"
|
||||
#include "source/fuzz/transformation_add_type_pointer.h"
|
||||
#include "source/fuzz/transformation_add_type_struct.h"
|
||||
#include "source/fuzz/transformation_add_type_vector.h"
|
||||
|
||||
namespace spvtools {
|
||||
@ -162,9 +163,8 @@ uint32_t FuzzerPass::FindOrCreateBoolType() {
|
||||
}
|
||||
|
||||
uint32_t FuzzerPass::FindOrCreateIntegerType(uint32_t width, bool is_signed) {
|
||||
opt::analysis::Integer int_type(width, is_signed);
|
||||
auto existing_id = GetIRContext()->get_type_mgr()->GetId(&int_type);
|
||||
if (existing_id) {
|
||||
if (auto existing_id =
|
||||
fuzzerutil::MaybeGetIntegerType(GetIRContext(), width, is_signed)) {
|
||||
return existing_id;
|
||||
}
|
||||
auto result = GetFuzzerContext()->GetFreshId();
|
||||
@ -173,9 +173,7 @@ uint32_t FuzzerPass::FindOrCreateIntegerType(uint32_t width, bool is_signed) {
|
||||
}
|
||||
|
||||
uint32_t FuzzerPass::FindOrCreateFloatType(uint32_t width) {
|
||||
opt::analysis::Float float_type(width);
|
||||
auto existing_id = GetIRContext()->get_type_mgr()->GetId(&float_type);
|
||||
if (existing_id) {
|
||||
if (auto existing_id = fuzzerutil::MaybeGetFloatType(GetIRContext(), width)) {
|
||||
return existing_id;
|
||||
}
|
||||
auto result = GetFuzzerContext()->GetFreshId();
|
||||
@ -205,14 +203,8 @@ uint32_t FuzzerPass::FindOrCreateFunctionType(
|
||||
|
||||
uint32_t FuzzerPass::FindOrCreateVectorType(uint32_t component_type_id,
|
||||
uint32_t component_count) {
|
||||
assert(component_count >= 2 && component_count <= 4 &&
|
||||
"Precondition: component count must be in range [2, 4].");
|
||||
opt::analysis::Type* component_type =
|
||||
GetIRContext()->get_type_mgr()->GetType(component_type_id);
|
||||
assert(component_type && "Precondition: the component type must exist.");
|
||||
opt::analysis::Vector vector_type(component_type, component_count);
|
||||
auto existing_id = GetIRContext()->get_type_mgr()->GetId(&vector_type);
|
||||
if (existing_id) {
|
||||
if (auto existing_id = fuzzerutil::MaybeGetVectorType(
|
||||
GetIRContext(), component_type_id, component_count)) {
|
||||
return existing_id;
|
||||
}
|
||||
auto result = GetFuzzerContext()->GetFreshId();
|
||||
@ -242,6 +234,17 @@ uint32_t FuzzerPass::FindOrCreateMatrixType(uint32_t column_count,
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t FuzzerPass::FindOrCreateStructType(
|
||||
const std::vector<uint32_t>& component_type_ids) {
|
||||
if (auto existing_id =
|
||||
fuzzerutil::MaybeGetStructType(GetIRContext(), component_type_ids)) {
|
||||
return existing_id;
|
||||
}
|
||||
auto new_id = GetFuzzerContext()->GetFreshId();
|
||||
ApplyTransformation(TransformationAddTypeStruct(new_id, component_type_ids));
|
||||
return new_id;
|
||||
}
|
||||
|
||||
uint32_t FuzzerPass::FindOrCreatePointerType(uint32_t base_type_id,
|
||||
SpvStorageClass storage_class) {
|
||||
// We do not use the type manager here, due to problems related to isomorphic
|
||||
|
@ -136,6 +136,13 @@ class FuzzerPass {
|
||||
// type itself do not exist, transformations are applied to add them.
|
||||
uint32_t FindOrCreateMatrixType(uint32_t column_count, uint32_t row_count);
|
||||
|
||||
// Returns the id of an OpTypeStruct instruction with |component_type_ids| as
|
||||
// type ids for struct's components. If no such a struct type exists,
|
||||
// transformations are applied to add it. |component_type_ids| may not contain
|
||||
// a result id of an OpTypeFunction.
|
||||
uint32_t FindOrCreateStructType(
|
||||
const std::vector<uint32_t>& component_type_ids);
|
||||
|
||||
// Returns the id of a pointer type with base type |base_type_id| (which must
|
||||
// already exist) and storage class |storage_class|. A transformation is
|
||||
// applied to add the pointer if it does not already exist.
|
||||
|
@ -729,6 +729,146 @@ uint32_t FindOrCreateFunctionType(opt::IRContext* ir_context,
|
||||
return result_id;
|
||||
}
|
||||
|
||||
uint32_t MaybeGetIntegerType(opt::IRContext* ir_context, uint32_t width,
|
||||
bool is_signed) {
|
||||
opt::analysis::Integer type(width, is_signed);
|
||||
return ir_context->get_type_mgr()->GetId(&type);
|
||||
}
|
||||
|
||||
uint32_t MaybeGetFloatType(opt::IRContext* ir_context, uint32_t width) {
|
||||
opt::analysis::Float type(width);
|
||||
return ir_context->get_type_mgr()->GetId(&type);
|
||||
}
|
||||
|
||||
uint32_t MaybeGetVectorType(opt::IRContext* ir_context,
|
||||
uint32_t component_type_id,
|
||||
uint32_t element_count) {
|
||||
const auto* component_type =
|
||||
ir_context->get_type_mgr()->GetType(component_type_id);
|
||||
assert(component_type &&
|
||||
(component_type->AsInteger() || component_type->AsFloat() ||
|
||||
component_type->AsBool()) &&
|
||||
"|component_type_id| is invalid");
|
||||
assert(element_count >= 2 && element_count <= 4 &&
|
||||
"Precondition: component count must be in range [2, 4].");
|
||||
opt::analysis::Vector type(component_type, element_count);
|
||||
return ir_context->get_type_mgr()->GetId(&type);
|
||||
}
|
||||
|
||||
uint32_t MaybeGetStructType(opt::IRContext* ir_context,
|
||||
const std::vector<uint32_t>& component_type_ids) {
|
||||
std::vector<const opt::analysis::Type*> component_types;
|
||||
component_types.reserve(component_type_ids.size());
|
||||
|
||||
for (auto type_id : component_type_ids) {
|
||||
const auto* component_type = ir_context->get_type_mgr()->GetType(type_id);
|
||||
assert(component_type && !component_type->AsFunction() &&
|
||||
"Component type is invalid");
|
||||
component_types.push_back(component_type);
|
||||
}
|
||||
|
||||
opt::analysis::Struct type(component_types);
|
||||
return ir_context->get_type_mgr()->GetId(&type);
|
||||
}
|
||||
|
||||
void AddIntegerType(opt::IRContext* ir_context, uint32_t result_id,
|
||||
uint32_t width, bool is_signed) {
|
||||
ir_context->module()->AddType(MakeUnique<opt::Instruction>(
|
||||
ir_context, SpvOpTypeInt, 0, result_id,
|
||||
opt::Instruction::OperandList{
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {width}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {is_signed ? 1u : 0u}}}));
|
||||
|
||||
UpdateModuleIdBound(ir_context, result_id);
|
||||
}
|
||||
|
||||
void AddFloatType(opt::IRContext* ir_context, uint32_t result_id,
|
||||
uint32_t width) {
|
||||
ir_context->module()->AddType(MakeUnique<opt::Instruction>(
|
||||
ir_context, SpvOpTypeFloat, 0, result_id,
|
||||
opt::Instruction::OperandList{
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {width}}}));
|
||||
|
||||
UpdateModuleIdBound(ir_context, result_id);
|
||||
}
|
||||
|
||||
void AddVectorType(opt::IRContext* ir_context, uint32_t result_id,
|
||||
uint32_t component_type_id, uint32_t element_count) {
|
||||
const auto* component_type =
|
||||
ir_context->get_type_mgr()->GetType(component_type_id);
|
||||
(void)component_type; // Make compiler happy in release mode.
|
||||
assert(component_type &&
|
||||
(component_type->AsInteger() || component_type->AsFloat() ||
|
||||
component_type->AsBool()) &&
|
||||
"|component_type_id| is invalid");
|
||||
assert(element_count >= 2 && element_count <= 4 &&
|
||||
"Precondition: component count must be in range [2, 4].");
|
||||
ir_context->module()->AddType(MakeUnique<opt::Instruction>(
|
||||
ir_context, SpvOpTypeVector, 0, result_id,
|
||||
opt::Instruction::OperandList{
|
||||
{SPV_OPERAND_TYPE_ID, {component_type_id}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {element_count}}}));
|
||||
|
||||
UpdateModuleIdBound(ir_context, result_id);
|
||||
}
|
||||
|
||||
void AddStructType(opt::IRContext* ir_context, uint32_t result_id,
|
||||
const std::vector<uint32_t>& component_type_ids) {
|
||||
opt::Instruction::OperandList operands;
|
||||
operands.reserve(component_type_ids.size());
|
||||
|
||||
for (auto type_id : component_type_ids) {
|
||||
const auto* type = ir_context->get_type_mgr()->GetType(type_id);
|
||||
(void)type; // Make compiler happy in release mode.
|
||||
assert(type && !type->AsFunction() && "Component's type id is invalid");
|
||||
operands.push_back({SPV_OPERAND_TYPE_ID, {type_id}});
|
||||
}
|
||||
|
||||
ir_context->AddType(MakeUnique<opt::Instruction>(
|
||||
ir_context, SpvOpTypeStruct, 0, result_id, std::move(operands)));
|
||||
|
||||
UpdateModuleIdBound(ir_context, result_id);
|
||||
}
|
||||
|
||||
uint32_t FindOrCreateIntegerType(opt::IRContext* ir_context, uint32_t result_id,
|
||||
uint32_t width, bool is_signed) {
|
||||
if (auto existing_id = MaybeGetIntegerType(ir_context, width, is_signed)) {
|
||||
return existing_id;
|
||||
}
|
||||
AddIntegerType(ir_context, result_id, width, is_signed);
|
||||
return result_id;
|
||||
}
|
||||
|
||||
uint32_t FindOrCreateFloatType(opt::IRContext* ir_context, uint32_t result_id,
|
||||
uint32_t width) {
|
||||
if (auto existing_id = MaybeGetFloatType(ir_context, width)) {
|
||||
return existing_id;
|
||||
}
|
||||
AddFloatType(ir_context, result_id, width);
|
||||
return result_id;
|
||||
}
|
||||
|
||||
uint32_t FindOrCreateVectorType(opt::IRContext* ir_context, uint32_t result_id,
|
||||
uint32_t component_type_id,
|
||||
uint32_t element_count) {
|
||||
if (auto existing_id =
|
||||
MaybeGetVectorType(ir_context, component_type_id, element_count)) {
|
||||
return existing_id;
|
||||
}
|
||||
AddVectorType(ir_context, result_id, component_type_id, element_count);
|
||||
return result_id;
|
||||
}
|
||||
|
||||
uint32_t FindOrCreateStructType(
|
||||
opt::IRContext* ir_context, uint32_t result_id,
|
||||
const std::vector<uint32_t>& component_type_ids) {
|
||||
if (auto existing_id = MaybeGetStructType(ir_context, component_type_ids)) {
|
||||
return existing_id;
|
||||
}
|
||||
AddStructType(ir_context, result_id, component_type_ids);
|
||||
return result_id;
|
||||
}
|
||||
|
||||
} // namespace fuzzerutil
|
||||
|
||||
} // namespace fuzz
|
||||
|
@ -284,6 +284,84 @@ uint32_t FindOrCreateFunctionType(opt::IRContext* ir_context,
|
||||
uint32_t result_id,
|
||||
const std::vector<uint32_t>& type_ids);
|
||||
|
||||
// Returns a result id of an OpTypeInt instruction if present. Returns 0
|
||||
// otherwise.
|
||||
uint32_t MaybeGetIntegerType(opt::IRContext* ir_context, uint32_t width,
|
||||
bool is_signed);
|
||||
|
||||
// Returns a result id of an OpTypeFloat instruction if present. Returns 0
|
||||
// otherwise.
|
||||
uint32_t MaybeGetFloatType(opt::IRContext* ir_context, uint32_t width);
|
||||
|
||||
// Returns a result id of an OpTypeVector instruction if present. Returns 0
|
||||
// otherwise. |component_type_id| must be a valid result id of an OpTypeInt,
|
||||
// OpTypeFloat or OpTypeBool instruction in the module. |element_count| must be
|
||||
// in the range [2, 4].
|
||||
uint32_t MaybeGetVectorType(opt::IRContext* ir_context,
|
||||
uint32_t component_type_id, uint32_t element_count);
|
||||
|
||||
// Returns a result id of an OpTypeStruct instruction if present. Returns 0
|
||||
// otherwise. |component_type_ids| may not contain a result id of an
|
||||
// OpTypeFunction.
|
||||
uint32_t MaybeGetStructType(opt::IRContext* ir_context,
|
||||
const std::vector<uint32_t>& component_type_ids);
|
||||
|
||||
// Creates a new OpTypeInt instruction in the module. Updates module's id bound
|
||||
// to accommodate for |result_id|.
|
||||
void AddIntegerType(opt::IRContext* ir_context, uint32_t result_id,
|
||||
uint32_t width, bool is_signed);
|
||||
|
||||
// Creates a new OpTypeFloat instruction in the module. Updates module's id
|
||||
// bound to accommodate for |result_id|.
|
||||
void AddFloatType(opt::IRContext* ir_context, uint32_t result_id,
|
||||
uint32_t width);
|
||||
|
||||
// Creates a new OpTypeVector instruction in the module. |component_type_id|
|
||||
// must be a valid result id of an OpTypeInt, OpTypeFloat or OpTypeBool
|
||||
// instruction in the module. |element_count| must be in the range [2, 4].
|
||||
// Updates module's id bound to accommodate for |result_id|.
|
||||
void AddVectorType(opt::IRContext* ir_context, uint32_t result_id,
|
||||
uint32_t component_type_id, uint32_t element_count);
|
||||
|
||||
// Creates a new OpTypeStruct instruction in the module. Updates module's id
|
||||
// bound to accommodate for |result_id|. |component_type_ids| may not contain
|
||||
// a result id of an OpTypeFunction.
|
||||
void AddStructType(opt::IRContext* ir_context, uint32_t result_id,
|
||||
const std::vector<uint32_t>& component_type_ids);
|
||||
|
||||
// Returns a result id of an OpTypeInt instruction in the module. Creates a new
|
||||
// instruction with |result_id|, if no required OpTypeInt is present in the
|
||||
// module, and returns |result_id|. Updates module's id bound to accommodate for
|
||||
// |result_id|.
|
||||
uint32_t FindOrCreateIntegerType(opt::IRContext* ir_context, uint32_t result_id,
|
||||
uint32_t width, bool is_signed);
|
||||
|
||||
// Returns a result id of an OpTypeFloat instruction in the module. Creates a
|
||||
// new instruction with |result_id|, if no required OpTypeFloat is present in
|
||||
// the module, and returns |result_id|. Updates module's id bound
|
||||
// to accommodate for |result_id|.
|
||||
uint32_t FindOrCreateFloatType(opt::IRContext* ir_context, uint32_t result_id,
|
||||
uint32_t width);
|
||||
|
||||
// Returns a result id of an OpTypeVector instruction in the module. Creates a
|
||||
// new instruction with |result_id|, if no required OpTypeVector is present in
|
||||
// the module, and returns |result_id|. |component_type_id| must be a valid
|
||||
// result id of an OpTypeInt, OpTypeFloat or OpTypeBool instruction in the
|
||||
// module. |element_count| must be in the range [2, 4]. Updates module's id
|
||||
// bound to accommodate for |result_id|.
|
||||
uint32_t FindOrCreateVectorType(opt::IRContext* ir_context, uint32_t result_id,
|
||||
uint32_t component_type_id,
|
||||
uint32_t element_count);
|
||||
|
||||
// Returns a result id of an OpTypeStruct instruction in the module. Creates a
|
||||
// new instruction with |result_id|, if no required OpTypeStruct is present in
|
||||
// the module, and returns |result_id|. Updates module's id bound
|
||||
// to accommodate for |result_id|. |component_type_ids| may not contain a result
|
||||
// id of an OpTypeFunction.
|
||||
uint32_t FindOrCreateStructType(
|
||||
opt::IRContext* ir_context, uint32_t result_id,
|
||||
const std::vector<uint32_t>& component_type_ids);
|
||||
|
||||
} // namespace fuzzerutil
|
||||
|
||||
} // namespace fuzz
|
||||
|
@ -73,6 +73,7 @@ void TransformationAddParameter::Apply(
|
||||
|
||||
auto parameter_type_id =
|
||||
fuzzerutil::GetTypeId(ir_context, message_.initializer_id());
|
||||
assert(parameter_type_id != 0 && "Initializer has invalid type");
|
||||
|
||||
// Add new parameters to the function.
|
||||
function->AddParameter(MakeUnique<opt::Instruction>(
|
||||
|
@ -38,17 +38,12 @@ bool TransformationAddTypeFloat::IsApplicable(
|
||||
|
||||
// Applicable if there is no float type with this width already declared in
|
||||
// the module.
|
||||
opt::analysis::Float float_type(message_.width());
|
||||
return ir_context->get_type_mgr()->GetId(&float_type) == 0;
|
||||
return fuzzerutil::MaybeGetFloatType(ir_context, message_.width()) == 0;
|
||||
}
|
||||
|
||||
void TransformationAddTypeFloat::Apply(
|
||||
opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
|
||||
opt::Instruction::OperandList width = {
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.width()}}};
|
||||
ir_context->module()->AddType(MakeUnique<opt::Instruction>(
|
||||
ir_context, SpvOpTypeFloat, 0, message_.fresh_id(), width));
|
||||
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
|
||||
fuzzerutil::AddFloatType(ir_context, message_.fresh_id(), message_.width());
|
||||
// We have added an instruction to the module, so need to be careful about the
|
||||
// validity of existing analyses.
|
||||
ir_context->InvalidateAnalysesExceptFor(
|
||||
|
@ -40,18 +40,14 @@ bool TransformationAddTypeInt::IsApplicable(
|
||||
|
||||
// Applicable if there is no int type with this width and signedness already
|
||||
// declared in the module.
|
||||
opt::analysis::Integer int_type(message_.width(), message_.is_signed());
|
||||
return ir_context->get_type_mgr()->GetId(&int_type) == 0;
|
||||
return fuzzerutil::MaybeGetIntegerType(ir_context, message_.width(),
|
||||
message_.is_signed()) == 0;
|
||||
}
|
||||
|
||||
void TransformationAddTypeInt::Apply(opt::IRContext* ir_context,
|
||||
TransformationContext* /*unused*/) const {
|
||||
opt::Instruction::OperandList in_operands = {
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.width()}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.is_signed() ? 1u : 0u}}};
|
||||
ir_context->module()->AddType(MakeUnique<opt::Instruction>(
|
||||
ir_context, SpvOpTypeInt, 0, message_.fresh_id(), in_operands));
|
||||
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
|
||||
fuzzerutil::AddIntegerType(ir_context, message_.fresh_id(), message_.width(),
|
||||
message_.is_signed());
|
||||
// We have added an instruction to the module, so need to be careful about the
|
||||
// validity of existing analyses.
|
||||
ir_context->InvalidateAnalysesExceptFor(
|
||||
|
@ -50,13 +50,10 @@ bool TransformationAddTypeStruct::IsApplicable(
|
||||
|
||||
void TransformationAddTypeStruct::Apply(
|
||||
opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
|
||||
opt::Instruction::OperandList in_operands;
|
||||
for (auto member_type : message_.member_type_id()) {
|
||||
in_operands.push_back({SPV_OPERAND_TYPE_ID, {member_type}});
|
||||
}
|
||||
ir_context->module()->AddType(MakeUnique<opt::Instruction>(
|
||||
ir_context, SpvOpTypeStruct, 0, message_.fresh_id(), in_operands));
|
||||
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
|
||||
fuzzerutil::AddStructType(
|
||||
ir_context, message_.fresh_id(),
|
||||
std::vector<uint32_t>(message_.member_type_id().begin(),
|
||||
message_.member_type_id().end()));
|
||||
// We have added an instruction to the module, so need to be careful about the
|
||||
// validity of existing analyses.
|
||||
ir_context->InvalidateAnalysesExceptFor(
|
||||
|
@ -46,13 +46,9 @@ bool TransformationAddTypeVector::IsApplicable(
|
||||
|
||||
void TransformationAddTypeVector::Apply(
|
||||
opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
|
||||
opt::Instruction::OperandList in_operands;
|
||||
in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.component_type_id()}});
|
||||
in_operands.push_back(
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.component_count()}});
|
||||
ir_context->module()->AddType(MakeUnique<opt::Instruction>(
|
||||
ir_context, SpvOpTypeVector, 0, message_.fresh_id(), in_operands));
|
||||
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
|
||||
fuzzerutil::AddVectorType(ir_context, message_.fresh_id(),
|
||||
message_.component_type_id(),
|
||||
message_.component_count());
|
||||
// We have added an instruction to the module, so need to be careful about the
|
||||
// validity of existing analyses.
|
||||
ir_context->InvalidateAnalysesExceptFor(
|
||||
|
Loading…
Reference in New Issue
Block a user