spirv-fuzz: Remove AddType methods from fuzzerutil (#4204)

Types should only be added to the module by spirv-fuzz via
transformations, so this change removes the AddType methods from
fuzzerutil, which were only called once each from the appropriate
transformation.

The transformations have been adapted so that they avoid redundantly
invalidating all analyses - they now update the def-use manager and
invalidate only the type manager.
This commit is contained in:
Alastair Donaldson 2021-03-20 08:54:51 +00:00 committed by GitHub
parent f2a19b0150
commit 75d7c14cfb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 121 additions and 142 deletions

View File

@ -1414,74 +1414,6 @@ uint32_t MaybeGetBoolConstant(
return 0;
}
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");
if (type->AsStruct()) {
// From the spec for the BuiltIn decoration:
// - When applied to a structure-type member, that structure type cannot
// be contained as a member of another structure type.
assert(!MembersHaveBuiltInDecoration(ir_context, type_id) &&
"A member struct has BuiltIn members");
}
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);
}
std::vector<uint32_t> IntToWords(uint64_t value, uint32_t width,
bool is_signed) {
assert(width <= 64 && "The bit width should not be more than 64 bits");

View File

@ -495,30 +495,6 @@ uint32_t MaybeGetBoolConstant(
const TransformationContext& transformation_context, bool value,
bool is_irrelevant);
// 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. if |component_type_ids| contains a result
// of an OpTypeStruct instruction, that struct may not have BuiltIn members.
void AddStructType(opt::IRContext* ir_context, uint32_t result_id,
const std::vector<uint32_t>& component_type_ids);
// Returns a vector of words representing the integer |value|, only considering
// the last |width| bits. The last |width| bits are sign-extended if the value
// is signed, zero-extended if it is unsigned.

View File

@ -69,13 +69,17 @@ void TransformationAddTypeArray::Apply(
opt::Instruction::OperandList in_operands;
in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.element_type_id()}});
in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.size_id()}});
ir_context->module()->AddType(MakeUnique<opt::Instruction>(
ir_context, SpvOpTypeArray, 0, message_.fresh_id(), in_operands));
auto type_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpTypeArray, 0, message_.fresh_id(), in_operands);
auto type_instruction_ptr = type_instruction.get();
ir_context->module()->AddType(std::move(type_instruction));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
// We have added an instruction to the module, so need to be careful about the
// validity of existing analyses.
ir_context->InvalidateAnalysesExceptFor(
opt::IRContext::Analysis::kAnalysisNone);
// Inform the def use manager that there is a new definition. Invalidate the
// type manager since we have added a new type.
ir_context->get_def_use_mgr()->AnalyzeInstDef(type_instruction_ptr);
ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisTypes);
}
protobufs::Transformation TransformationAddTypeArray::ToMessage() const {

View File

@ -42,13 +42,17 @@ bool TransformationAddTypeBoolean::IsApplicable(
void TransformationAddTypeBoolean::Apply(
opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
opt::Instruction::OperandList empty_operands;
ir_context->module()->AddType(MakeUnique<opt::Instruction>(
ir_context, SpvOpTypeBool, 0, message_.fresh_id(), empty_operands));
auto type_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpTypeBool, 0, message_.fresh_id(), empty_operands);
auto type_instruction_ptr = type_instruction.get();
ir_context->module()->AddType(std::move(type_instruction));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
// We have added an instruction to the module, so need to be careful about the
// validity of existing analyses.
ir_context->InvalidateAnalysesExceptFor(
opt::IRContext::Analysis::kAnalysisNone);
// Inform the def use manager that there is a new definition. Invalidate the
// type manager since we have added a new type.
ir_context->get_def_use_mgr()->AnalyzeInstDef(type_instruction_ptr);
ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisTypes);
}
protobufs::Transformation TransformationAddTypeBoolean::ToMessage() const {

View File

@ -65,11 +65,18 @@ bool TransformationAddTypeFloat::IsApplicable(
void TransformationAddTypeFloat::Apply(
opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
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(
opt::IRContext::Analysis::kAnalysisNone);
auto type_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpTypeFloat, 0, message_.fresh_id(),
opt::Instruction::OperandList{
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.width()}}});
auto type_instruction_ptr = type_instruction.get();
ir_context->module()->AddType(std::move(type_instruction));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
// Inform the def use manager that there is a new definition, and invalidate
// the type manager since we have added a new type.
ir_context->get_def_use_mgr()->AnalyzeInstDef(type_instruction_ptr);
ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisTypes);
}
protobufs::Transformation TransformationAddTypeFloat::ToMessage() const {

View File

@ -74,12 +74,21 @@ bool TransformationAddTypeInt::IsApplicable(
void TransformationAddTypeInt::Apply(opt::IRContext* ir_context,
TransformationContext* /*unused*/) const {
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(
opt::IRContext::Analysis::kAnalysisNone);
auto type_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpTypeInt, 0, message_.fresh_id(),
opt::Instruction::OperandList{
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.width()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER,
{message_.is_signed() ? 1u : 0u}}});
auto type_instruction_ptr = type_instruction.get();
ir_context->module()->AddType(std::move(type_instruction));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
// Inform the def use manager that there is a new definition. Invalidate the
// type manager since we have added a new type.
ir_context->get_def_use_mgr()->AnalyzeInstDef(type_instruction_ptr);
ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisTypes);
}
protobufs::Transformation TransformationAddTypeInt::ToMessage() const {

View File

@ -52,13 +52,17 @@ void TransformationAddTypeMatrix::Apply(
in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.column_type_id()}});
in_operands.push_back(
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.column_count()}});
ir_context->module()->AddType(MakeUnique<opt::Instruction>(
ir_context, SpvOpTypeMatrix, 0, message_.fresh_id(), in_operands));
auto type_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpTypeMatrix, 0, message_.fresh_id(), in_operands);
auto type_instruction_ptr = type_instruction.get();
ir_context->module()->AddType(std::move(type_instruction));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
// We have added an instruction to the module, so need to be careful about the
// validity of existing analyses.
ir_context->InvalidateAnalysesExceptFor(
opt::IRContext::Analysis::kAnalysisNone);
// Inform the def use manager that there is a new definition. Invalidate the
// type manager since we have added a new type.
ir_context->get_def_use_mgr()->AnalyzeInstDef(type_instruction_ptr);
ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisTypes);
}
protobufs::Transformation TransformationAddTypeMatrix::ToMessage() const {

View File

@ -47,13 +47,17 @@ void TransformationAddTypePointer::Apply(
opt::Instruction::OperandList in_operands = {
{SPV_OPERAND_TYPE_STORAGE_CLASS, {message_.storage_class()}},
{SPV_OPERAND_TYPE_ID, {message_.base_type_id()}}};
ir_context->module()->AddType(MakeUnique<opt::Instruction>(
ir_context, SpvOpTypePointer, 0, message_.fresh_id(), in_operands));
auto type_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpTypePointer, 0, message_.fresh_id(), in_operands);
auto type_instruction_ptr = type_instruction.get();
ir_context->module()->AddType(std::move(type_instruction));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
// We have added an instruction to the module, so need to be careful about the
// validity of existing analyses.
ir_context->InvalidateAnalysesExceptFor(
opt::IRContext::Analysis::kAnalysisNone);
// Inform the def use manager that there is a new definition. Invalidate the
// type manager since we have added a new type.
ir_context->get_def_use_mgr()->AnalyzeInstDef(type_instruction_ptr);
ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisTypes);
}
protobufs::Transformation TransformationAddTypePointer::ToMessage() const {

View File

@ -58,14 +58,36 @@ bool TransformationAddTypeStruct::IsApplicable(
void TransformationAddTypeStruct::Apply(
opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
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(
opt::IRContext::Analysis::kAnalysisNone);
opt::Instruction::OperandList operands;
operands.reserve(message_.member_type_id().size());
for (auto type_id : message_.member_type_id()) {
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");
if (type->AsStruct()) {
// From the spec for the BuiltIn decoration:
// - When applied to a structure-type member, that structure type cannot
// be contained as a member of another structure type.
assert(!fuzzerutil::MembersHaveBuiltInDecoration(ir_context, type_id) &&
"A member struct has BuiltIn members");
}
operands.push_back({SPV_OPERAND_TYPE_ID, {type_id}});
}
auto type_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpTypeStruct, 0, message_.fresh_id(), std::move(operands));
auto type_instruction_ptr = type_instruction.get();
ir_context->AddType(std::move(type_instruction));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
// Inform the def use manager that there is a new definition. Invalidate the
// type manager since we have added a new type.
ir_context->get_def_use_mgr()->AnalyzeInstDef(type_instruction_ptr);
ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisTypes);
}
protobufs::Transformation TransformationAddTypeStruct::ToMessage() const {

View File

@ -46,13 +46,30 @@ bool TransformationAddTypeVector::IsApplicable(
void TransformationAddTypeVector::Apply(
opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
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(
opt::IRContext::Analysis::kAnalysisNone);
const auto* component_type =
ir_context->get_type_mgr()->GetType(message_.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(message_.component_count() >= 2 && message_.component_count() <= 4 &&
"Precondition: component count must be in range [2, 4].");
auto type_instruction = MakeUnique<opt::Instruction>(
ir_context, SpvOpTypeVector, 0, message_.fresh_id(),
opt::Instruction::OperandList{
{SPV_OPERAND_TYPE_ID, {message_.component_type_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.component_count()}}});
auto type_instruction_ptr = type_instruction.get();
ir_context->module()->AddType(std::move(type_instruction));
fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
// Inform the def use manager that there is a new definition. Invalidate the
// type manager since we have added a new type.
ir_context->get_def_use_mgr()->AnalyzeInstDef(type_instruction_ptr);
ir_context->InvalidateAnalyses(opt::IRContext::kAnalysisTypes);
}
protobufs::Transformation TransformationAddTypeVector::ToMessage() const {