spirv-fuzz: Transformations to add types, constants and variables (#3101)

This change adds several transformations that allow types, constants,
undefined values and global variables to be added to a module.
This commit is contained in:
Alastair Donaldson 2019-12-16 23:54:13 +00:00 committed by GitHub
parent fccbc00aca
commit 38d7fbaad0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 2389 additions and 0 deletions

View File

@ -62,14 +62,22 @@ if(SPIRV_BUILD_FUZZER)
shrinker.h
transformation.h
transformation_add_constant_boolean.h
transformation_add_constant_composite.h
transformation_add_constant_scalar.h
transformation_add_dead_break.h
transformation_add_dead_continue.h
transformation_add_global_undef.h
transformation_add_global_variable.h
transformation_add_no_contraction_decoration.h
transformation_add_type_array.h
transformation_add_type_boolean.h
transformation_add_type_float.h
transformation_add_type_function.h
transformation_add_type_int.h
transformation_add_type_matrix.h
transformation_add_type_pointer.h
transformation_add_type_struct.h
transformation_add_type_vector.h
transformation_composite_construct.h
transformation_composite_extract.h
transformation_copy_object.h
@ -119,14 +127,22 @@ if(SPIRV_BUILD_FUZZER)
shrinker.cpp
transformation.cpp
transformation_add_constant_boolean.cpp
transformation_add_constant_composite.cpp
transformation_add_constant_scalar.cpp
transformation_add_dead_break.cpp
transformation_add_dead_continue.cpp
transformation_add_global_undef.cpp
transformation_add_global_variable.cpp
transformation_add_no_contraction_decoration.cpp
transformation_add_type_array.cpp
transformation_add_type_boolean.cpp
transformation_add_type_float.cpp
transformation_add_type_function.cpp
transformation_add_type_int.cpp
transformation_add_type_matrix.cpp
transformation_add_type_pointer.cpp
transformation_add_type_struct.cpp
transformation_add_type_vector.cpp
transformation_composite_construct.cpp
transformation_composite_extract.cpp
transformation_copy_object.cpp

View File

@ -312,6 +312,11 @@ std::unique_ptr<opt::IRContext> CloneIRContext(opt::IRContext* context) {
binary.size());
}
bool IsNonFunctionTypeId(opt::IRContext* ir_context, uint32_t id) {
auto type = ir_context->get_type_mgr()->GetType(id);
return type && !type->AsFunction();
}
} // namespace fuzzerutil
} // namespace fuzz

View File

@ -116,6 +116,10 @@ bool IsValid(opt::IRContext* context);
// parsing it again.
std::unique_ptr<opt::IRContext> CloneIRContext(opt::IRContext* context);
// Returns true if and only if |id| is the id of a type that is not a function
// type.
bool IsNonFunctionTypeId(opt::IRContext* ir_context, uint32_t id);
} // namespace fuzzerutil
} // namespace fuzz

View File

@ -202,6 +202,14 @@ message Transformation {
TransformationVectorShuffle vector_shuffle = 22;
TransformationOutlineFunction outline_function = 23;
TransformationMergeBlocks merge_blocks = 24;
TransformationAddTypeVector add_type_vector = 25;
TransformationAddTypeArray add_type_array = 26;
TransformationAddTypeMatrix add_type_matrix = 27;
TransformationAddTypeStruct add_type_struct = 28;
TransformationAddTypeFunction add_type_function = 29;
TransformationAddConstantComposite add_constant_composite = 30;
TransformationAddGlobalVariable add_global_variable = 31;
TransformationAddGlobalUndef add_global_undef = 32;
// Add additional option using the next available number.
}
}
@ -218,6 +226,21 @@ message TransformationAddConstantBoolean {
}
message TransformationAddConstantComposite {
// Adds a constant of the given composite type to the module.
// Fresh id for the composite
uint32 fresh_id = 1;
// A composite type id
uint32 type_id = 2;
// Constituent ids for the composite
repeated uint32 constituent_id = 3;
}
message TransformationAddConstantScalar {
// Adds a constant of the given scalar type
@ -274,6 +297,34 @@ message TransformationAddDeadContinue {
}
message TransformationAddGlobalUndef {
// Adds an undefined value of a given type to the module at global scope.
// Fresh id for the undefined value
uint32 fresh_id = 1;
// The type of the undefined value
uint32 type_id = 2;
}
message TransformationAddGlobalVariable {
// Adds a global variable of the given type to the module, with Private
// storage class and optionally with an initializer.
// Fresh id for the global variable
uint32 fresh_id = 1;
// The type of the global variable
uint32 type_id = 2;
// Optional initializer; 0 if there is no initializer
uint32 initializer_id = 3;
}
message TransformationAddNoContractionDecoration {
// Applies OpDecorate NoContraction to the given result id
@ -283,6 +334,21 @@ message TransformationAddNoContractionDecoration {
}
message TransformationAddTypeArray {
// Adds an array type of the given element type and size to the module
// Fresh id for the array type
uint32 fresh_id = 1;
// The array's element type
uint32 element_type_id = 2;
// The array's size
uint32 size_id = 3;
}
message TransformationAddTypeBoolean {
// Adds OpTypeBool to the module
@ -304,6 +370,21 @@ message TransformationAddTypeFloat {
}
message TransformationAddTypeFunction {
// Adds a function type to the module
// Fresh id for the function type
uint32 fresh_id = 1;
// The function's return type
uint32 return_type_id = 2;
// The function's argument types
repeated uint32 argument_type_id = 3;
}
message TransformationAddTypeInt {
// Adds OpTypeInt to the module with the given width and signedness
@ -319,6 +400,22 @@ message TransformationAddTypeInt {
}
message TransformationAddTypeMatrix {
// Adds a matrix type to the module
// Fresh id for the matrix type
uint32 fresh_id = 1;
// The matrix's column type, which must be a floating-point vector (as per
// the "data rules" in the SPIR-V specification).
uint32 column_type_id = 2;
// The matrix's column count
uint32 column_count = 3;
}
message TransformationAddTypePointer {
// Adds OpTypePointer to the module, with the given storage class and base
@ -335,6 +432,33 @@ message TransformationAddTypePointer {
}
message TransformationAddTypeStruct {
// Adds a struct type to the module
// Fresh id for the struct type
uint32 fresh_id = 1;
// The struct's member types
repeated uint32 member_type_id = 3;
}
message TransformationAddTypeVector {
// Adds a vector type to the module
// Fresh id for the vector type
uint32 fresh_id = 1;
// The vector's component type
uint32 component_type_id = 2;
// The vector's component count
uint32 component_count = 3;
}
message TransformationCompositeConstruct {
// A transformation that introduces an OpCompositeConstruct instruction to

View File

@ -17,14 +17,22 @@
#include <cassert>
#include "source/fuzz/transformation_add_constant_boolean.h"
#include "source/fuzz/transformation_add_constant_composite.h"
#include "source/fuzz/transformation_add_constant_scalar.h"
#include "source/fuzz/transformation_add_dead_break.h"
#include "source/fuzz/transformation_add_dead_continue.h"
#include "source/fuzz/transformation_add_global_undef.h"
#include "source/fuzz/transformation_add_global_variable.h"
#include "source/fuzz/transformation_add_no_contraction_decoration.h"
#include "source/fuzz/transformation_add_type_array.h"
#include "source/fuzz/transformation_add_type_boolean.h"
#include "source/fuzz/transformation_add_type_float.h"
#include "source/fuzz/transformation_add_type_function.h"
#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"
#include "source/fuzz/transformation_composite_construct.h"
#include "source/fuzz/transformation_composite_extract.h"
#include "source/fuzz/transformation_copy_object.h"
@ -53,6 +61,9 @@ std::unique_ptr<Transformation> Transformation::FromMessage(
case protobufs::Transformation::TransformationCase::kAddConstantBoolean:
return MakeUnique<TransformationAddConstantBoolean>(
message.add_constant_boolean());
case protobufs::Transformation::TransformationCase::kAddConstantComposite:
return MakeUnique<TransformationAddConstantComposite>(
message.add_constant_composite());
case protobufs::Transformation::TransformationCase::kAddConstantScalar:
return MakeUnique<TransformationAddConstantScalar>(
message.add_constant_scalar());
@ -61,20 +72,37 @@ std::unique_ptr<Transformation> Transformation::FromMessage(
case protobufs::Transformation::TransformationCase::kAddDeadContinue:
return MakeUnique<TransformationAddDeadContinue>(
message.add_dead_continue());
case protobufs::Transformation::TransformationCase::kAddGlobalUndef:
return MakeUnique<TransformationAddGlobalUndef>(
message.add_global_undef());
case protobufs::Transformation::TransformationCase::kAddGlobalVariable:
return MakeUnique<TransformationAddGlobalVariable>(
message.add_global_variable());
case protobufs::Transformation::TransformationCase::
kAddNoContractionDecoration:
return MakeUnique<TransformationAddNoContractionDecoration>(
message.add_no_contraction_decoration());
case protobufs::Transformation::TransformationCase::kAddTypeArray:
return MakeUnique<TransformationAddTypeArray>(message.add_type_array());
case protobufs::Transformation::TransformationCase::kAddTypeBoolean:
return MakeUnique<TransformationAddTypeBoolean>(
message.add_type_boolean());
case protobufs::Transformation::TransformationCase::kAddTypeFloat:
return MakeUnique<TransformationAddTypeFloat>(message.add_type_float());
case protobufs::Transformation::TransformationCase::kAddTypeFunction:
return MakeUnique<TransformationAddTypeFunction>(
message.add_type_function());
case protobufs::Transformation::TransformationCase::kAddTypeInt:
return MakeUnique<TransformationAddTypeInt>(message.add_type_int());
case protobufs::Transformation::TransformationCase::kAddTypeMatrix:
return MakeUnique<TransformationAddTypeMatrix>(message.add_type_matrix());
case protobufs::Transformation::TransformationCase::kAddTypePointer:
return MakeUnique<TransformationAddTypePointer>(
message.add_type_pointer());
case protobufs::Transformation::TransformationCase::kAddTypeStruct:
return MakeUnique<TransformationAddTypeStruct>(message.add_type_struct());
case protobufs::Transformation::TransformationCase::kAddTypeVector:
return MakeUnique<TransformationAddTypeVector>(message.add_type_vector());
case protobufs::Transformation::TransformationCase::kCompositeConstruct:
return MakeUnique<TransformationCompositeConstruct>(
message.composite_construct());

View File

@ -0,0 +1,130 @@
// Copyright (c) 2019 Google LLC
//
// 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/transformation_add_constant_composite.h"
#include <vector>
#include "source/fuzz/fuzzer_util.h"
namespace spvtools {
namespace fuzz {
TransformationAddConstantComposite::TransformationAddConstantComposite(
const spvtools::fuzz::protobufs::TransformationAddConstantComposite&
message)
: message_(message) {}
TransformationAddConstantComposite::TransformationAddConstantComposite(
uint32_t fresh_id, uint32_t type_id,
const std::vector<uint32_t>& constituent_ids) {
message_.set_fresh_id(fresh_id);
message_.set_type_id(type_id);
for (auto constituent_id : constituent_ids) {
message_.add_constituent_id(constituent_id);
}
}
bool TransformationAddConstantComposite::IsApplicable(
opt::IRContext* context,
const spvtools::fuzz::FactManager& /*unused*/) const {
// Check that the given id is fresh.
if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
return false;
}
// Check that the composite type id is an instruction id.
auto composite_type_instruction =
context->get_def_use_mgr()->GetDef(message_.type_id());
if (!composite_type_instruction) {
return false;
}
// Gather up the operands for the composite constant, in the process checking
// whether the given type really defines a composite.
std::vector<uint32_t> constituent_type_ids;
switch (composite_type_instruction->opcode()) {
case SpvOpTypeArray:
for (uint32_t index = 0;
index <
fuzzerutil::GetArraySize(*composite_type_instruction, context);
index++) {
constituent_type_ids.push_back(
composite_type_instruction->GetSingleWordInOperand(0));
}
break;
case SpvOpTypeMatrix:
case SpvOpTypeVector:
for (uint32_t index = 0;
index < composite_type_instruction->GetSingleWordInOperand(1);
index++) {
constituent_type_ids.push_back(
composite_type_instruction->GetSingleWordInOperand(0));
}
break;
case SpvOpTypeStruct:
composite_type_instruction->ForEachInOperand(
[&constituent_type_ids](const uint32_t* member_type_id) {
constituent_type_ids.push_back(*member_type_id);
});
break;
default:
// Not a composite type.
return false;
}
// Check that the number of provided operands matches the number of
// constituents required by the type.
if (constituent_type_ids.size() !=
static_cast<uint32_t>(message_.constituent_id().size())) {
return false;
}
// Check that every provided operand refers to an instruction of the
// corresponding constituent type.
for (uint32_t index = 0; index < constituent_type_ids.size(); index++) {
auto constituent_instruction =
context->get_def_use_mgr()->GetDef(message_.constituent_id(index));
if (!constituent_instruction) {
return false;
}
if (constituent_instruction->type_id() != constituent_type_ids.at(index)) {
return false;
}
}
return true;
}
void TransformationAddConstantComposite::Apply(
opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
opt::Instruction::OperandList in_operands;
for (auto constituent_id : message_.constituent_id()) {
in_operands.push_back({SPV_OPERAND_TYPE_ID, {constituent_id}});
}
context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
context, SpvOpConstantComposite, message_.type_id(), message_.fresh_id(),
in_operands));
fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
// We have added an instruction to the module, so need to be careful about the
// validity of existing analyses.
context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
}
protobufs::Transformation TransformationAddConstantComposite::ToMessage()
const {
protobufs::Transformation result;
*result.mutable_add_constant_composite() = message_;
return result;
}
} // namespace fuzz
} // namespace spvtools

View File

@ -0,0 +1,58 @@
// Copyright (c) 2019 Google LLC
//
// 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_TRANSFORMATION_ADD_CONSTANT_COMPOSITE_H_
#define SOURCE_FUZZ_TRANSFORMATION_ADD_CONSTANT_COMPOSITE_H_
#include <vector>
#include "source/fuzz/fact_manager.h"
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/fuzz/transformation.h"
#include "source/opt/ir_context.h"
namespace spvtools {
namespace fuzz {
class TransformationAddConstantComposite : public Transformation {
public:
explicit TransformationAddConstantComposite(
const protobufs::TransformationAddConstantComposite& message);
TransformationAddConstantComposite(
uint32_t fresh_id, uint32_t type_id,
const std::vector<uint32_t>& constituent_ids);
// - |message_.fresh_id| must be a fresh id
// - |message_.type_id| must be the id of a composite type
// - |message_.constituent_id| must refer to ids that match the constituent
// types of this composite type
bool IsApplicable(opt::IRContext* context,
const FactManager& fact_manager) const override;
// Adds an OpConstantComposite instruction defining a constant of type
// |message_.type_id|, using |message_.constituent_id| as constituents, with
// result id |message_.fresh_id|.
void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
protobufs::Transformation ToMessage() const override;
private:
protobufs::TransformationAddConstantComposite message_;
};
} // namespace fuzz
} // namespace spvtools
#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_CONSTANT_COMPOSITE_H_

View File

@ -0,0 +1,62 @@
// Copyright (c) 2019 Google LLC
//
// 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/transformation_add_global_undef.h"
#include "source/fuzz/fuzzer_util.h"
namespace spvtools {
namespace fuzz {
TransformationAddGlobalUndef::TransformationAddGlobalUndef(
const spvtools::fuzz::protobufs::TransformationAddGlobalUndef& message)
: message_(message) {}
TransformationAddGlobalUndef::TransformationAddGlobalUndef(uint32_t fresh_id,
uint32_t type_id) {
message_.set_fresh_id(fresh_id);
message_.set_type_id(type_id);
}
bool TransformationAddGlobalUndef::IsApplicable(
opt::IRContext* context,
const spvtools::fuzz::FactManager& /*unused*/) const {
// A fresh id is required.
if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
return false;
}
auto type = context->get_type_mgr()->GetType(message_.type_id());
// The type must exist, and must not be a function type.
return type && !type->AsFunction();
}
void TransformationAddGlobalUndef::Apply(
opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
context, SpvOpUndef, message_.type_id(), message_.fresh_id(),
opt::Instruction::OperandList()));
fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
// We have added an instruction to the module, so need to be careful about the
// validity of existing analyses.
context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
}
protobufs::Transformation TransformationAddGlobalUndef::ToMessage() const {
protobufs::Transformation result;
*result.mutable_add_global_undef() = message_;
return result;
}
} // namespace fuzz
} // namespace spvtools

View File

@ -0,0 +1,51 @@
// Copyright (c) 2019 Google LLC
//
// 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_TRANSFORMATION_ADD_GLOBAL_UNDEF_H_
#define SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_UNDEF_H_
#include "source/fuzz/fact_manager.h"
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/fuzz/transformation.h"
#include "source/opt/ir_context.h"
namespace spvtools {
namespace fuzz {
class TransformationAddGlobalUndef : public Transformation {
public:
explicit TransformationAddGlobalUndef(
const protobufs::TransformationAddGlobalUndef& message);
TransformationAddGlobalUndef(uint32_t fresh_id, uint32_t type_id);
// - |message_.fresh_id| must be fresh
// - |message_.type_id| must be the id of a non-function type
bool IsApplicable(opt::IRContext* context,
const FactManager& fact_manager) const override;
// Adds an OpUndef instruction to the module, with |message_.type_id| as its
// type. The instruction has result id |message_.fresh_id|.
void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
protobufs::Transformation ToMessage() const override;
private:
protobufs::TransformationAddGlobalUndef message_;
};
} // namespace fuzz
} // namespace spvtools
#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_UNDEF_H_

View File

@ -0,0 +1,98 @@
// Copyright (c) 2019 Google LLC
//
// 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/transformation_add_global_variable.h"
#include "source/fuzz/fuzzer_util.h"
namespace spvtools {
namespace fuzz {
TransformationAddGlobalVariable::TransformationAddGlobalVariable(
const spvtools::fuzz::protobufs::TransformationAddGlobalVariable& message)
: message_(message) {}
TransformationAddGlobalVariable::TransformationAddGlobalVariable(
uint32_t fresh_id, uint32_t type_id, uint32_t initializer_id) {
message_.set_fresh_id(fresh_id);
message_.set_type_id(type_id);
message_.set_initializer_id(initializer_id);
}
bool TransformationAddGlobalVariable::IsApplicable(
opt::IRContext* context,
const spvtools::fuzz::FactManager& /*unused*/) const {
// The result id must be fresh.
if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
return false;
}
// The type id must correspond to a type.
auto type = context->get_type_mgr()->GetType(message_.type_id());
if (!type) {
return false;
}
// That type must be a pointer type ...
auto pointer_type = type->AsPointer();
if (!pointer_type) {
return false;
}
// ... with Private storage class.
if (pointer_type->storage_class() != SpvStorageClassPrivate) {
return false;
}
if (message_.initializer_id()) {
// The initializer id must be the id of a constant. Check this with the
// constant manager.
auto constant_id = context->get_constant_mgr()->GetConstantsFromIds(
{message_.initializer_id()});
if (constant_id.empty()) {
return false;
}
assert(constant_id.size() == 1 &&
"We asked for the constant associated with a single id; we should "
"get a single constant.");
// The type of the constant must match the pointee type of the pointer.
if (pointer_type->pointee_type() != constant_id[0]->type()) {
return false;
}
}
return true;
}
void TransformationAddGlobalVariable::Apply(
opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
opt::Instruction::OperandList input_operands;
input_operands.push_back(
{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassPrivate}});
if (message_.initializer_id()) {
input_operands.push_back(
{SPV_OPERAND_TYPE_ID, {message_.initializer_id()}});
}
context->module()->AddGlobalValue(
MakeUnique<opt::Instruction>(context, SpvOpVariable, message_.type_id(),
message_.fresh_id(), input_operands));
fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
// We have added an instruction to the module, so need to be careful about the
// validity of existing analyses.
context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
}
protobufs::Transformation TransformationAddGlobalVariable::ToMessage() const {
protobufs::Transformation result;
*result.mutable_add_global_variable() = message_;
return result;
}
} // namespace fuzz
} // namespace spvtools

View File

@ -0,0 +1,57 @@
// Copyright (c) 2019 Google LLC
//
// 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_TRANSFORMATION_ADD_GLOBAL_VARIABLE_H_
#define SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_VARIABLE_H_
#include "source/fuzz/fact_manager.h"
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/fuzz/transformation.h"
#include "source/opt/ir_context.h"
namespace spvtools {
namespace fuzz {
class TransformationAddGlobalVariable : public Transformation {
public:
explicit TransformationAddGlobalVariable(
const protobufs::TransformationAddGlobalVariable& message);
TransformationAddGlobalVariable(uint32_t fresh_id, uint32_t type_id,
uint32_t initializer_id);
// - |message_.fresh_id| must be fresh
// - |message_.type_id| must be the id of a pointer type with Private storage
// class
// - |message_.initializer_id| must either be 0 or the id of a constant whose
// type is the pointee type of |message_.type_id|
bool IsApplicable(opt::IRContext* context,
const FactManager& fact_manager) const override;
// Adds a global variable with Private storage class to the module, with type
// |message_.type_id| and either no initializer or |message_.initializer_id|
// as an initializer, depending on whether |message_.initializer_id| is 0.
// The global variable has result id |message_.fresh_id|.
void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
protobufs::Transformation ToMessage() const override;
private:
protobufs::TransformationAddGlobalVariable message_;
};
} // namespace fuzz
} // namespace spvtools
#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_GLOBAL_VARIABLE_H_

View File

@ -0,0 +1,88 @@
// Copyright (c) 2019 Google LLC
//
// 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/transformation_add_type_array.h"
#include "source/fuzz/fuzzer_util.h"
namespace spvtools {
namespace fuzz {
TransformationAddTypeArray::TransformationAddTypeArray(
const spvtools::fuzz::protobufs::TransformationAddTypeArray& message)
: message_(message) {}
TransformationAddTypeArray::TransformationAddTypeArray(uint32_t fresh_id,
uint32_t element_type_id,
uint32_t size_id) {
message_.set_fresh_id(fresh_id);
message_.set_element_type_id(element_type_id);
message_.set_size_id(size_id);
}
bool TransformationAddTypeArray::IsApplicable(
opt::IRContext* context,
const spvtools::fuzz::FactManager& /*unused*/) const {
// A fresh id is required.
if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
return false;
}
auto element_type =
context->get_type_mgr()->GetType(message_.element_type_id());
if (!element_type || element_type->AsFunction()) {
// The element type id either does not refer to a type, or refers to a
// function type; both are illegal.
return false;
}
auto constant =
context->get_constant_mgr()->GetConstantsFromIds({message_.size_id()});
if (constant.empty()) {
// The size id does not refer to a constant.
return false;
}
assert(constant.size() == 1 &&
"Only one constant id was provided, so only one constant should have "
"been returned");
auto int_constant = constant[0]->AsIntConstant();
if (!int_constant) {
// The size constant is not an integer.
return false;
}
// We require that the size constant be a 32-bit value that is positive when
// interpreted as being signed.
return int_constant->words().size() == 1 && int_constant->GetS32() >= 1;
}
void TransformationAddTypeArray::Apply(
opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
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()}});
context->module()->AddType(MakeUnique<opt::Instruction>(
context, SpvOpTypeArray, 0, message_.fresh_id(), in_operands));
fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
// We have added an instruction to the module, so need to be careful about the
// validity of existing analyses.
context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
}
protobufs::Transformation TransformationAddTypeArray::ToMessage() const {
protobufs::Transformation result;
*result.mutable_add_type_array() = message_;
return result;
}
} // namespace fuzz
} // namespace spvtools

View File

@ -0,0 +1,55 @@
// Copyright (c) 2019 Google LLC
//
// 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_TRANSFORMATION_ADD_TYPE_ARRAY_H_
#define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_ARRAY_H_
#include "source/fuzz/fact_manager.h"
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/fuzz/transformation.h"
#include "source/opt/ir_context.h"
namespace spvtools {
namespace fuzz {
class TransformationAddTypeArray : public Transformation {
public:
explicit TransformationAddTypeArray(
const protobufs::TransformationAddTypeArray& message);
TransformationAddTypeArray(uint32_t fresh_id, uint32_t element_type_id,
uint32_t size_id);
// - |message_.fresh_id| must be fresh
// - |message_.element_type_id| must be the id of a non-function type
// - |message_.size_id| must be the id of a 32-bit integer constant that is
// positive when interpreted as signed.
bool IsApplicable(opt::IRContext* context,
const FactManager& fact_manager) const override;
// Adds an OpTypeArray instruction to the module, with element type given by
// |message_.element_type_id| and size given by |message_.size_id|. The
// result id of the instruction is |message_.fresh_id|.
void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
protobufs::Transformation ToMessage() const override;
private:
protobufs::TransformationAddTypeArray message_;
};
} // namespace fuzz
} // namespace spvtools
#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_ARRAY_H_

View File

@ -0,0 +1,113 @@
// Copyright (c) 2019 Google LLC
//
// 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/transformation_add_type_function.h"
#include <vector>
#include "source/fuzz/fuzzer_util.h"
namespace spvtools {
namespace fuzz {
TransformationAddTypeFunction::TransformationAddTypeFunction(
const spvtools::fuzz::protobufs::TransformationAddTypeFunction& message)
: message_(message) {}
TransformationAddTypeFunction::TransformationAddTypeFunction(
uint32_t fresh_id, uint32_t return_type_id,
const std::vector<uint32_t>& argument_type_ids) {
message_.set_fresh_id(fresh_id);
message_.set_return_type_id(return_type_id);
for (auto id : argument_type_ids) {
message_.add_argument_type_id(id);
}
}
bool TransformationAddTypeFunction::IsApplicable(
opt::IRContext* context,
const spvtools::fuzz::FactManager& /*unused*/) const {
// The result id must be fresh.
if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
return false;
}
// The return and argument types must be type ids but not not be function
// type ids.
if (!fuzzerutil::IsNonFunctionTypeId(context, message_.return_type_id())) {
return false;
}
for (auto argument_type_id : message_.argument_type_id()) {
if (!fuzzerutil::IsNonFunctionTypeId(context, argument_type_id)) {
return false;
}
}
// Check whether there is already an OpTypeFunction definition that uses
// exactly the same return and argument type ids. (Note that the type manager
// does not allow us to check this, as it does not distinguish between
// function types with different but isomorphic pointer argument types.)
for (auto& inst : context->module()->types_values()) {
if (inst.opcode() != SpvOpTypeFunction) {
// Consider only OpTypeFunction instructions.
continue;
}
if (inst.GetSingleWordInOperand(0) != message_.return_type_id()) {
// Different return types - cannot be the same.
continue;
}
if (inst.NumInOperands() !=
1 + static_cast<uint32_t>(message_.argument_type_id().size())) {
// Different numbers of arguments - cannot be the same.
continue;
}
bool found_argument_mismatch = false;
for (uint32_t index = 1; index < inst.NumInOperands(); index++) {
if (message_.argument_type_id(index - 1) !=
inst.GetSingleWordInOperand(index)) {
// Argument mismatch - cannot be the same.
found_argument_mismatch = true;
break;
}
}
if (found_argument_mismatch) {
continue;
}
// Everything matches - the type is already declared.
return false;
}
return true;
}
void TransformationAddTypeFunction::Apply(
opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
opt::Instruction::OperandList in_operands;
in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.return_type_id()}});
for (auto argument_type_id : message_.argument_type_id()) {
in_operands.push_back({SPV_OPERAND_TYPE_ID, {argument_type_id}});
}
context->module()->AddType(MakeUnique<opt::Instruction>(
context, SpvOpTypeFunction, 0, message_.fresh_id(), in_operands));
fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
// We have added an instruction to the module, so need to be careful about the
// validity of existing analyses.
context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
}
protobufs::Transformation TransformationAddTypeFunction::ToMessage() const {
protobufs::Transformation result;
*result.mutable_add_type_function() = message_;
return result;
}
} // namespace fuzz
} // namespace spvtools

View File

@ -0,0 +1,59 @@
// Copyright (c) 2019 Google LLC
//
// 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_TRANSFORMATION_ADD_TYPE_FUNCTION_H_
#define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_FUNCTION_H_
#include <vector>
#include "source/fuzz/fact_manager.h"
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/fuzz/transformation.h"
#include "source/opt/ir_context.h"
namespace spvtools {
namespace fuzz {
class TransformationAddTypeFunction : public Transformation {
public:
explicit TransformationAddTypeFunction(
const protobufs::TransformationAddTypeFunction& message);
TransformationAddTypeFunction(uint32_t fresh_id, uint32_t return_type_id,
const std::vector<uint32_t>& argument_type_ids);
// - |message_.fresh_id| must not be used by the module
// - |message_.return_type_id| and each element of |message_.argument_type_id|
// must be the ids of non-function types
// - The module must not contain an OpTypeFunction instruction defining a
// function type with the signature provided by teh given return and
// argument types
bool IsApplicable(opt::IRContext* context,
const FactManager& fact_manager) const override;
// Adds an OpTypeFunction instruction to the module, with signature given by
// |message_.return_type_id| and |message_.argument_type_id|. The result id
// for the instruction is |message_.fresh_id|.
void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
protobufs::Transformation ToMessage() const override;
private:
protobufs::TransformationAddTypeFunction message_;
};
} // namespace fuzz
} // namespace spvtools
#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_FUNCTION_H_

View File

@ -0,0 +1,71 @@
// Copyright (c) 2019 Google LLC
//
// 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/transformation_add_type_matrix.h"
#include "fuzzer_util.h"
namespace spvtools {
namespace fuzz {
TransformationAddTypeMatrix::TransformationAddTypeMatrix(
const spvtools::fuzz::protobufs::TransformationAddTypeMatrix& message)
: message_(message) {}
TransformationAddTypeMatrix::TransformationAddTypeMatrix(
uint32_t fresh_id, uint32_t column_type_id, uint32_t column_count) {
message_.set_fresh_id(fresh_id);
message_.set_column_type_id(column_type_id);
message_.set_column_count(column_count);
}
bool TransformationAddTypeMatrix::IsApplicable(
opt::IRContext* context,
const spvtools::fuzz::FactManager& /*unused*/) const {
// The result id must be fresh.
if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
return false;
}
// The column type must be a floating-point vector.
auto column_type =
context->get_type_mgr()->GetType(message_.column_type_id());
if (!column_type) {
return false;
}
return column_type->AsVector() &&
column_type->AsVector()->element_type()->AsFloat();
}
void TransformationAddTypeMatrix::Apply(
opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/) const {
opt::Instruction::OperandList in_operands;
in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.column_type_id()}});
in_operands.push_back(
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.column_count()}});
context->module()->AddType(MakeUnique<opt::Instruction>(
context, SpvOpTypeMatrix, 0, message_.fresh_id(), in_operands));
fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
// We have added an instruction to the module, so need to be careful about the
// validity of existing analyses.
context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
}
protobufs::Transformation TransformationAddTypeMatrix::ToMessage() const {
protobufs::Transformation result;
*result.mutable_add_type_matrix() = message_;
return result;
}
} // namespace fuzz
} // namespace spvtools

View File

@ -0,0 +1,53 @@
// Copyright (c) 2019 Google LLC
//
// 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_TRANSFORMATION_ADD_TYPE_MATRIX_H_
#define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_MATRIX_H_
#include "source/fuzz/fact_manager.h"
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/fuzz/transformation.h"
#include "source/opt/ir_context.h"
namespace spvtools {
namespace fuzz {
class TransformationAddTypeMatrix : public Transformation {
public:
explicit TransformationAddTypeMatrix(
const protobufs::TransformationAddTypeMatrix& message);
TransformationAddTypeMatrix(uint32_t fresh_id, uint32_t base_type_id,
uint32_t size);
// - |message_.fresh_id| must be a fresh id
// - |message_.column_type_id| must be the id of a floating-point vector type
bool IsApplicable(opt::IRContext* context,
const FactManager& fact_manager) const override;
// Adds an OpTypeMatrix instruction to the module, with column type
// |message_.column_type_id| and |message_.column_count| columns, with result
// id |message_.fresh_id|.
void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
protobufs::Transformation ToMessage() const override;
private:
protobufs::TransformationAddTypeMatrix message_;
};
} // namespace fuzz
} // namespace spvtools
#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_MATRIX_H_

View File

@ -0,0 +1,73 @@
// Copyright (c) 2019 Google LLC
//
// 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/transformation_add_type_struct.h"
#include "source/fuzz/fuzzer_util.h"
namespace spvtools {
namespace fuzz {
TransformationAddTypeStruct::TransformationAddTypeStruct(
const spvtools::fuzz::protobufs::TransformationAddTypeStruct& message)
: message_(message) {}
TransformationAddTypeStruct::TransformationAddTypeStruct(
uint32_t fresh_id, const std::vector<uint32_t>& member_type_ids) {
message_.set_fresh_id(fresh_id);
for (auto member_type_id : member_type_ids) {
message_.add_member_type_id(member_type_id);
}
}
bool TransformationAddTypeStruct::IsApplicable(
opt::IRContext* context,
const spvtools::fuzz::FactManager& /*unused*/) const {
// A fresh id is required.
if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
return false;
}
for (auto member_type : message_.member_type_id()) {
auto type = context->get_type_mgr()->GetType(member_type);
if (!type || type->AsFunction()) {
// The member type id either does not refer to a type, or refers to a
// function type; both are illegal.
return false;
}
}
return true;
}
void TransformationAddTypeStruct::Apply(
opt::IRContext* context, spvtools::fuzz::FactManager* /*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}});
}
context->module()->AddType(MakeUnique<opt::Instruction>(
context, SpvOpTypeStruct, 0, message_.fresh_id(), in_operands));
fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
// We have added an instruction to the module, so need to be careful about the
// validity of existing analyses.
context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
}
protobufs::Transformation TransformationAddTypeStruct::ToMessage() const {
protobufs::Transformation result;
*result.mutable_add_type_struct() = message_;
return result;
}
} // namespace fuzz
} // namespace spvtools

View File

@ -0,0 +1,54 @@
// Copyright (c) 2019 Google LLC
//
// 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_TRANSFORMATION_ADD_TYPE_STRUCT_H_
#define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_STRUCT_H_
#include <vector>
#include "source/fuzz/fact_manager.h"
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/fuzz/transformation.h"
#include "source/opt/ir_context.h"
namespace spvtools {
namespace fuzz {
class TransformationAddTypeStruct : public Transformation {
public:
explicit TransformationAddTypeStruct(
const protobufs::TransformationAddTypeStruct& message);
TransformationAddTypeStruct(uint32_t fresh_id,
const std::vector<uint32_t>& component_type_ids);
// - |message_.fresh_id| must be a fresh id
// - |message_.member_type_id| must be a sequence of non-function type ids
bool IsApplicable(opt::IRContext* context,
const FactManager& fact_manager) const override;
// Adds an OpTypeStruct instruction whose field types are given by
// |message_.member_type_id|, with result id |message_.fresh_id|.
void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
protobufs::Transformation ToMessage() const override;
private:
protobufs::TransformationAddTypeStruct message_;
};
} // namespace fuzz
} // namespace spvtools
#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_STRUCT_H_

View File

@ -0,0 +1,69 @@
// Copyright (c) 2019 Google LLC
//
// 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/transformation_add_type_vector.h"
#include "fuzzer_util.h"
namespace spvtools {
namespace fuzz {
TransformationAddTypeVector::TransformationAddTypeVector(
const spvtools::fuzz::protobufs::TransformationAddTypeVector& message)
: message_(message) {}
TransformationAddTypeVector::TransformationAddTypeVector(
uint32_t fresh_id, uint32_t component_type_id, uint32_t component_count) {
message_.set_fresh_id(fresh_id);
message_.set_component_type_id(component_type_id);
message_.set_component_count(component_count);
}
bool TransformationAddTypeVector::IsApplicable(
opt::IRContext* context,
const spvtools::fuzz::FactManager& /*unused*/) const {
if (!fuzzerutil::IsFreshId(context, message_.fresh_id())) {
return false;
}
auto component_type =
context->get_type_mgr()->GetType(message_.component_type_id());
if (!component_type) {
return false;
}
return component_type->AsBool() || component_type->AsFloat() ||
component_type->AsInteger();
}
void TransformationAddTypeVector::Apply(
opt::IRContext* context, spvtools::fuzz::FactManager* /*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()}});
context->module()->AddType(MakeUnique<opt::Instruction>(
context, SpvOpTypeVector, 0, message_.fresh_id(), in_operands));
fuzzerutil::UpdateModuleIdBound(context, message_.fresh_id());
// We have added an instruction to the module, so need to be careful about the
// validity of existing analyses.
context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
}
protobufs::Transformation TransformationAddTypeVector::ToMessage() const {
protobufs::Transformation result;
*result.mutable_add_type_vector() = message_;
return result;
}
} // namespace fuzz
} // namespace spvtools

View File

@ -0,0 +1,53 @@
// Copyright (c) 2019 Google LLC
//
// 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_TRANSFORMATION_ADD_TYPE_VECTOR_H_
#define SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_VECTOR_H_
#include "source/fuzz/fact_manager.h"
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/fuzz/transformation.h"
#include "source/opt/ir_context.h"
namespace spvtools {
namespace fuzz {
class TransformationAddTypeVector : public Transformation {
public:
explicit TransformationAddTypeVector(
const protobufs::TransformationAddTypeVector& message);
TransformationAddTypeVector(uint32_t fresh_id, uint32_t base_type_id,
uint32_t size);
// - |message_.fresh_id| must be a fresh id
// - |message_.component_type_id| must be the id of a scalar type
bool IsApplicable(opt::IRContext* context,
const FactManager& fact_manager) const override;
// Adds an OpTypeVector instruction to the module, with component type
// |message_.component_type_id| and |message_.component_count| components,
// with result id |message_.fresh_id|.
void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
protobufs::Transformation ToMessage() const override;
private:
protobufs::TransformationAddTypeVector message_;
};
} // namespace fuzz
} // namespace spvtools
#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_TYPE_VECTOR_H_

View File

@ -24,14 +24,22 @@ if (${SPIRV_BUILD_FUZZER})
fuzzer_pass_add_useful_constructs_test.cpp
instruction_descriptor_test.cpp
transformation_add_constant_boolean_test.cpp
transformation_add_constant_composite_test.cpp
transformation_add_constant_scalar_test.cpp
transformation_add_dead_break_test.cpp
transformation_add_dead_continue_test.cpp
transformation_add_global_undef_test.cpp
transformation_add_global_variable_test.cpp
transformation_add_no_contraction_decoration_test.cpp
transformation_add_type_array_test.cpp
transformation_add_type_boolean_test.cpp
transformation_add_type_float_test.cpp
transformation_add_type_function_test.cpp
transformation_add_type_int_test.cpp
transformation_add_type_matrix_test.cpp
transformation_add_type_pointer_test.cpp
transformation_add_type_struct_test.cpp
transformation_add_type_vector_test.cpp
transformation_composite_construct_test.cpp
transformation_composite_extract_test.cpp
transformation_copy_object_test.cpp

View File

@ -0,0 +1,158 @@
// Copyright (c) 2019 Google LLC
//
// 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/transformation_add_constant_composite.h"
#include "test/fuzz/fuzz_test_util.h"
namespace spvtools {
namespace fuzz {
namespace {
TEST(TransformationAddConstantCompositeTest, BasicTest) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeVector %6 2
%8 = OpTypeMatrix %7 3
%11 = OpConstant %6 0
%12 = OpConstant %6 1
%14 = OpConstant %6 2
%15 = OpConstant %6 3
%17 = OpConstant %6 4
%18 = OpConstant %6 5
%21 = OpTypeInt 32 1
%22 = OpTypeInt 32 0
%23 = OpConstant %22 3
%24 = OpTypeArray %21 %23
%25 = OpTypeBool
%26 = OpTypeStruct %24 %25
%29 = OpConstant %21 1
%30 = OpConstant %21 2
%31 = OpConstant %21 3
%33 = OpConstantFalse %25
%35 = OpTypeVector %6 3
%38 = OpConstant %6 6
%39 = OpConstant %6 7
%40 = OpConstant %6 8
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_4;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
// Too few ids
ASSERT_FALSE(TransformationAddConstantComposite(103, 8, {100, 101})
.IsApplicable(context.get(), fact_manager));
// Too many ids
ASSERT_FALSE(TransformationAddConstantComposite(101, 7, {14, 15, 14})
.IsApplicable(context.get(), fact_manager));
// Id already in use
ASSERT_FALSE(TransformationAddConstantComposite(40, 7, {11, 12})
.IsApplicable(context.get(), fact_manager));
// %39 is not a type
ASSERT_FALSE(TransformationAddConstantComposite(100, 39, {11, 12})
.IsApplicable(context.get(), fact_manager));
TransformationAddConstantComposite transformations[] = {
// %100 = OpConstantComposite %7 %11 %12
TransformationAddConstantComposite(100, 7, {11, 12}),
// %101 = OpConstantComposite %7 %14 %15
TransformationAddConstantComposite(101, 7, {14, 15}),
// %102 = OpConstantComposite %7 %17 %18
TransformationAddConstantComposite(102, 7, {17, 18}),
// %103 = OpConstantComposite %8 %100 %101 %102
TransformationAddConstantComposite(103, 8, {100, 101, 102}),
// %104 = OpConstantComposite %24 %29 %30 %31
TransformationAddConstantComposite(104, 24, {29, 30, 31}),
// %105 = OpConstantComposite %26 %104 %33
TransformationAddConstantComposite(105, 26, {104, 33}),
// %106 = OpConstantComposite %35 %38 %39 %40
TransformationAddConstantComposite(106, 35, {38, 39, 40})};
for (auto& transformation : transformations) {
ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
transformation.Apply(context.get(), &fact_manager);
}
ASSERT_TRUE(IsValid(env, context.get()));
std::string after_transformation = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeVector %6 2
%8 = OpTypeMatrix %7 3
%11 = OpConstant %6 0
%12 = OpConstant %6 1
%14 = OpConstant %6 2
%15 = OpConstant %6 3
%17 = OpConstant %6 4
%18 = OpConstant %6 5
%21 = OpTypeInt 32 1
%22 = OpTypeInt 32 0
%23 = OpConstant %22 3
%24 = OpTypeArray %21 %23
%25 = OpTypeBool
%26 = OpTypeStruct %24 %25
%29 = OpConstant %21 1
%30 = OpConstant %21 2
%31 = OpConstant %21 3
%33 = OpConstantFalse %25
%35 = OpTypeVector %6 3
%38 = OpConstant %6 6
%39 = OpConstant %6 7
%40 = OpConstant %6 8
%100 = OpConstantComposite %7 %11 %12
%101 = OpConstantComposite %7 %14 %15
%102 = OpConstantComposite %7 %17 %18
%103 = OpConstantComposite %8 %100 %101 %102
%104 = OpConstantComposite %24 %29 %30 %31
%105 = OpConstantComposite %26 %104 %33
%106 = OpConstantComposite %35 %38 %39 %40
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
} // namespace
} // namespace fuzz
} // namespace spvtools

View File

@ -0,0 +1,118 @@
// Copyright (c) 2019 Google LLC
//
// 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/transformation_add_global_undef.h"
#include "test/fuzz/fuzz_test_util.h"
namespace spvtools {
namespace fuzz {
namespace {
TEST(TransformationAddGlobalUndefTest, BasicTest) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeInt 32 1
%8 = OpTypeVector %6 2
%9 = OpTypeVector %6 3
%10 = OpTypeVector %6 4
%11 = OpTypeVector %7 2
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_4;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
// Id already in use
ASSERT_FALSE(TransformationAddGlobalUndef(4, 11).IsApplicable(context.get(),
fact_manager));
// %1 is not a type
ASSERT_FALSE(TransformationAddGlobalUndef(100, 1).IsApplicable(context.get(),
fact_manager));
// %3 is a function type
ASSERT_FALSE(TransformationAddGlobalUndef(100, 3).IsApplicable(context.get(),
fact_manager));
TransformationAddGlobalUndef transformations[] = {
// %100 = OpUndef %6
TransformationAddGlobalUndef(100, 6),
// %101 = OpUndef %7
TransformationAddGlobalUndef(101, 7),
// %102 = OpUndef %8
TransformationAddGlobalUndef(102, 8),
// %103 = OpUndef %9
TransformationAddGlobalUndef(103, 9),
// %104 = OpUndef %10
TransformationAddGlobalUndef(104, 10),
// %105 = OpUndef %11
TransformationAddGlobalUndef(105, 11)};
for (auto& transformation : transformations) {
ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
transformation.Apply(context.get(), &fact_manager);
}
ASSERT_TRUE(IsValid(env, context.get()));
std::string after_transformation = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeInt 32 1
%8 = OpTypeVector %6 2
%9 = OpTypeVector %6 3
%10 = OpTypeVector %6 4
%11 = OpTypeVector %7 2
%100 = OpUndef %6
%101 = OpUndef %7
%102 = OpUndef %8
%103 = OpUndef %9
%104 = OpUndef %10
%105 = OpUndef %11
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
} // namespace
} // namespace fuzz
} // namespace spvtools

View File

@ -0,0 +1,172 @@
// Copyright (c) 2019 Google LLC
//
// 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/transformation_add_global_variable.h"
#include "test/fuzz/fuzz_test_util.h"
namespace spvtools {
namespace fuzz {
namespace {
TEST(TransformationAddGlobalVariableTest, BasicTest) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeInt 32 1
%8 = OpTypeVector %6 2
%9 = OpTypePointer Function %6
%10 = OpTypePointer Private %6
%20 = OpTypePointer Uniform %6
%11 = OpTypePointer Function %7
%12 = OpTypePointer Private %7
%13 = OpTypePointer Private %8
%14 = OpVariable %10 Private
%15 = OpVariable %20 Uniform
%16 = OpConstant %7 1
%17 = OpTypePointer Private %10
%18 = OpTypeBool
%19 = OpTypePointer Private %18
%21 = OpConstantTrue %18
%22 = OpConstantFalse %18
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_4;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
// Id already in use
ASSERT_FALSE(TransformationAddGlobalVariable(4, 10, 0).IsApplicable(
context.get(), fact_manager));
// %1 is not a type
ASSERT_FALSE(TransformationAddGlobalVariable(100, 1, 0).IsApplicable(
context.get(), fact_manager));
// %7 is not a pointer type
ASSERT_FALSE(TransformationAddGlobalVariable(100, 7, 0).IsApplicable(
context.get(), fact_manager));
// %9 does not have Private storage class
ASSERT_FALSE(TransformationAddGlobalVariable(100, 9, 0).IsApplicable(
context.get(), fact_manager));
// %15 does not have Private storage class
ASSERT_FALSE(TransformationAddGlobalVariable(100, 15, 0)
.IsApplicable(context.get(), fact_manager));
// %10 is a pointer to float, while %16 is an int constant
ASSERT_FALSE(TransformationAddGlobalVariable(100, 10, 16)
.IsApplicable(context.get(), fact_manager));
// %10 is a Private pointer to float, while %15 is a variable with type
// Uniform float pointer
ASSERT_FALSE(TransformationAddGlobalVariable(100, 10, 15)
.IsApplicable(context.get(), fact_manager));
// %12 is a Private pointer to int, while %10 is a variable with type
// Private float pointer
ASSERT_FALSE(TransformationAddGlobalVariable(100, 12, 10)
.IsApplicable(context.get(), fact_manager));
// %10 is pointer-to-float, and %14 has type pointer-to-float; that's not OK
// since the initializer's type should be the *pointee* type.
ASSERT_FALSE(TransformationAddGlobalVariable(104, 10, 14)
.IsApplicable(context.get(), fact_manager));
// This would work in principle, but logical addressing does not allow
// a pointer to a pointer.
ASSERT_FALSE(TransformationAddGlobalVariable(104, 17, 14)
.IsApplicable(context.get(), fact_manager));
TransformationAddGlobalVariable transformations[] = {
// %100 = OpVariable %12 Private
TransformationAddGlobalVariable(100, 12, 0),
// %101 = OpVariable %10 Private
TransformationAddGlobalVariable(101, 10, 0),
// %102 = OpVariable %13 Private
TransformationAddGlobalVariable(102, 13, 0),
// %103 = OpVariable %12 Private %16
TransformationAddGlobalVariable(103, 12, 16),
// %104 = OpVariable %19 Private %21
TransformationAddGlobalVariable(104, 19, 21),
// %105 = OpVariable %19 Private %22
TransformationAddGlobalVariable(105, 19, 22)};
for (auto& transformation : transformations) {
ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
transformation.Apply(context.get(), &fact_manager);
}
ASSERT_TRUE(IsValid(env, context.get()));
std::string after_transformation = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeInt 32 1
%8 = OpTypeVector %6 2
%9 = OpTypePointer Function %6
%10 = OpTypePointer Private %6
%20 = OpTypePointer Uniform %6
%11 = OpTypePointer Function %7
%12 = OpTypePointer Private %7
%13 = OpTypePointer Private %8
%14 = OpVariable %10 Private
%15 = OpVariable %20 Uniform
%16 = OpConstant %7 1
%17 = OpTypePointer Private %10
%18 = OpTypeBool
%19 = OpTypePointer Private %18
%21 = OpConstantTrue %18
%22 = OpConstantFalse %18
%100 = OpVariable %12 Private
%101 = OpVariable %10 Private
%102 = OpVariable %13 Private
%103 = OpVariable %12 Private %16
%104 = OpVariable %19 Private %21
%105 = OpVariable %19 Private %22
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
} // namespace
} // namespace fuzz
} // namespace spvtools

View File

@ -0,0 +1,136 @@
// Copyright (c) 2019 Google LLC
//
// 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/transformation_add_type_array.h"
#include "test/fuzz/fuzz_test_util.h"
namespace spvtools {
namespace fuzz {
namespace {
TEST(TransformationAddTypeArrayTest, BasicTest) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeInt 32 1
%8 = OpTypeVector %6 2
%9 = OpTypeVector %6 3
%10 = OpTypeVector %6 4
%11 = OpTypeVector %7 2
%12 = OpConstant %7 3
%13 = OpConstant %7 0
%14 = OpConstant %7 -1
%15 = OpTypeInt 32 0
%16 = OpConstant %15 5
%17 = OpConstant %15 0
%18 = OpConstant %6 1
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_4;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
// Id already in use
ASSERT_FALSE(TransformationAddTypeArray(4, 10, 16).IsApplicable(
context.get(), fact_manager));
// %1 is not a type
ASSERT_FALSE(TransformationAddTypeArray(100, 1, 16)
.IsApplicable(context.get(), fact_manager));
// %3 is a function type
ASSERT_FALSE(TransformationAddTypeArray(100, 3, 16)
.IsApplicable(context.get(), fact_manager));
// %2 is not a constant
ASSERT_FALSE(TransformationAddTypeArray(100, 11, 2)
.IsApplicable(context.get(), fact_manager));
// %18 is not an integer
ASSERT_FALSE(TransformationAddTypeArray(100, 11, 18)
.IsApplicable(context.get(), fact_manager));
// %13 is signed 0
ASSERT_FALSE(TransformationAddTypeArray(100, 11, 13)
.IsApplicable(context.get(), fact_manager));
// %14 is negative
ASSERT_FALSE(TransformationAddTypeArray(100, 11, 14)
.IsApplicable(context.get(), fact_manager));
// %17 is unsigned 0
ASSERT_FALSE(TransformationAddTypeArray(100, 11, 17)
.IsApplicable(context.get(), fact_manager));
TransformationAddTypeArray transformations[] = {
// %100 = OpTypeArray %10 %16
TransformationAddTypeArray(100, 10, 16),
// %101 = OpTypeArray %7 %12
TransformationAddTypeArray(101, 7, 12)};
for (auto& transformation : transformations) {
ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
transformation.Apply(context.get(), &fact_manager);
}
ASSERT_TRUE(IsValid(env, context.get()));
std::string after_transformation = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeInt 32 1
%8 = OpTypeVector %6 2
%9 = OpTypeVector %6 3
%10 = OpTypeVector %6 4
%11 = OpTypeVector %7 2
%12 = OpConstant %7 3
%13 = OpConstant %7 0
%14 = OpConstant %7 -1
%15 = OpTypeInt 32 0
%16 = OpConstant %15 5
%17 = OpConstant %15 0
%18 = OpConstant %6 1
%100 = OpTypeArray %10 %16
%101 = OpTypeArray %7 %12
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
} // namespace
} // namespace fuzz
} // namespace spvtools

View File

@ -0,0 +1,134 @@
// Copyright (c) 2019 Google LLC
//
// 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/transformation_add_type_function.h"
#include "test/fuzz/fuzz_test_util.h"
namespace spvtools {
namespace fuzz {
namespace {
TEST(TransformationAddTypeFunctionTest, BasicTest) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%7 = OpTypePointer Function %6
%8 = OpTypeFunction %2 %7
%12 = OpTypeFloat 32
%13 = OpTypeStruct %6 %12
%14 = OpTypePointer Function %13
%200 = OpTypePointer Function %13
%15 = OpTypeVector %12 3
%16 = OpTypePointer Function %15
%17 = OpTypeVector %12 2
%18 = OpTypeFunction %17 %14 %16
%23 = OpConstant %12 1
%24 = OpConstantComposite %17 %23 %23
%27 = OpConstant %6 3
%30 = OpConstant %6 1
%31 = OpConstant %12 2
%32 = OpConstantComposite %13 %30 %31
%33 = OpConstantComposite %15 %23 %23 %23
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_4;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
// Id already in use
ASSERT_FALSE(TransformationAddTypeFunction(4, 12, {12, 16, 14})
.IsApplicable(context.get(), fact_manager));
// %1 is not a type
ASSERT_FALSE(TransformationAddTypeFunction(100, 1, {12, 16, 14})
.IsApplicable(context.get(), fact_manager));
// %18 is a function type
ASSERT_FALSE(TransformationAddTypeFunction(100, 12, {18})
.IsApplicable(context.get(), fact_manager));
// A function of this signature already exists
ASSERT_FALSE(TransformationAddTypeFunction(100, 17, {14, 16})
.IsApplicable(context.get(), fact_manager));
TransformationAddTypeFunction transformations[] = {
// %100 = OpTypeFunction %12 %12 %16 %14
TransformationAddTypeFunction(100, 12, {12, 16, 14}),
// %101 = OpTypeFunction %12
TransformationAddTypeFunction(101, 12, {}),
// %102 = OpTypeFunction %17 %200 %16
TransformationAddTypeFunction(102, 17, {200, 16})};
for (auto& transformation : transformations) {
ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
transformation.Apply(context.get(), &fact_manager);
}
ASSERT_TRUE(IsValid(env, context.get()));
std::string after_transformation = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%7 = OpTypePointer Function %6
%8 = OpTypeFunction %2 %7
%12 = OpTypeFloat 32
%13 = OpTypeStruct %6 %12
%14 = OpTypePointer Function %13
%200 = OpTypePointer Function %13
%15 = OpTypeVector %12 3
%16 = OpTypePointer Function %15
%17 = OpTypeVector %12 2
%18 = OpTypeFunction %17 %14 %16
%23 = OpConstant %12 1
%24 = OpConstantComposite %17 %23 %23
%27 = OpConstant %6 3
%30 = OpConstant %6 1
%31 = OpConstant %12 2
%32 = OpConstantComposite %13 %30 %31
%33 = OpConstantComposite %15 %23 %23 %23
%100 = OpTypeFunction %12 %12 %16 %14
%101 = OpTypeFunction %12
%102 = OpTypeFunction %17 %200 %16
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
} // namespace
} // namespace fuzz
} // namespace spvtools

View File

@ -0,0 +1,130 @@
// Copyright (c) 2019 Google LLC
//
// 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/transformation_add_type_matrix.h"
#include "test/fuzz/fuzz_test_util.h"
namespace spvtools {
namespace fuzz {
namespace {
TEST(TransformationAddTypeMatrixTest, BasicTest) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeInt 32 1
%8 = OpTypeVector %6 2
%9 = OpTypeVector %6 3
%10 = OpTypeVector %6 4
%11 = OpTypeVector %7 2
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_4;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
// Id already in use
ASSERT_FALSE(TransformationAddTypeMatrix(4, 9, 2).IsApplicable(context.get(),
fact_manager));
// %1 is not a type
ASSERT_FALSE(TransformationAddTypeMatrix(100, 1, 2).IsApplicable(
context.get(), fact_manager));
// %11 is not a floating-point vector
ASSERT_FALSE(TransformationAddTypeMatrix(100, 11, 2)
.IsApplicable(context.get(), fact_manager));
TransformationAddTypeMatrix transformations[] = {
// %100 = OpTypeMatrix %8 2
TransformationAddTypeMatrix(100, 8, 2),
// %101 = OpTypeMatrix %8 3
TransformationAddTypeMatrix(101, 8, 3),
// %102 = OpTypeMatrix %8 4
TransformationAddTypeMatrix(102, 8, 4),
// %103 = OpTypeMatrix %9 2
TransformationAddTypeMatrix(103, 9, 2),
// %104 = OpTypeMatrix %9 3
TransformationAddTypeMatrix(104, 9, 3),
// %105 = OpTypeMatrix %9 4
TransformationAddTypeMatrix(105, 9, 4),
// %106 = OpTypeMatrix %10 2
TransformationAddTypeMatrix(106, 10, 2),
// %107 = OpTypeMatrix %10 3
TransformationAddTypeMatrix(107, 10, 3),
// %108 = OpTypeMatrix %10 4
TransformationAddTypeMatrix(108, 10, 4)};
for (auto& transformation : transformations) {
ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
transformation.Apply(context.get(), &fact_manager);
}
ASSERT_TRUE(IsValid(env, context.get()));
std::string after_transformation = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeInt 32 1
%8 = OpTypeVector %6 2
%9 = OpTypeVector %6 3
%10 = OpTypeVector %6 4
%11 = OpTypeVector %7 2
%100 = OpTypeMatrix %8 2
%101 = OpTypeMatrix %8 3
%102 = OpTypeMatrix %8 4
%103 = OpTypeMatrix %9 2
%104 = OpTypeMatrix %9 3
%105 = OpTypeMatrix %9 4
%106 = OpTypeMatrix %10 2
%107 = OpTypeMatrix %10 3
%108 = OpTypeMatrix %10 4
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
} // namespace
} // namespace fuzz
} // namespace spvtools

View File

@ -0,0 +1,110 @@
// Copyright (c) 2019 Google LLC
//
// 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/transformation_add_type_struct.h"
#include "test/fuzz/fuzz_test_util.h"
namespace spvtools {
namespace fuzz {
namespace {
TEST(TransformationAddTypeStructTest, BasicTest) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeInt 32 1
%8 = OpTypeVector %6 2
%9 = OpTypeVector %6 3
%10 = OpTypeVector %6 4
%11 = OpTypeVector %7 2
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_4;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
// Id already in use
ASSERT_FALSE(TransformationAddTypeStruct(4, {}).IsApplicable(context.get(),
fact_manager));
// %1 is not a type
ASSERT_FALSE(TransformationAddTypeStruct(100, {1}).IsApplicable(
context.get(), fact_manager));
// %3 is a function type
ASSERT_FALSE(TransformationAddTypeStruct(100, {3}).IsApplicable(
context.get(), fact_manager));
TransformationAddTypeStruct transformations[] = {
// %100 = OpTypeStruct %6 %7 %8 %9 %10 %11
TransformationAddTypeStruct(100, {6, 7, 8, 9, 10, 11}),
// %101 = OpTypeStruct
TransformationAddTypeStruct(101, {}),
// %102 = OpTypeStruct %6
TransformationAddTypeStruct(102, {6}),
// %103 = OpTypeStruct %6 %6
TransformationAddTypeStruct(103, {6, 6})};
for (auto& transformation : transformations) {
ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
transformation.Apply(context.get(), &fact_manager);
}
ASSERT_TRUE(IsValid(env, context.get()));
std::string after_transformation = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeInt 32 1
%8 = OpTypeVector %6 2
%9 = OpTypeVector %6 3
%10 = OpTypeVector %6 4
%11 = OpTypeVector %7 2
%100 = OpTypeStruct %6 %7 %8 %9 %10 %11
%101 = OpTypeStruct
%102 = OpTypeStruct %6
%103 = OpTypeStruct %6 %6
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
} // namespace
} // namespace fuzz
} // namespace spvtools

View File

@ -0,0 +1,102 @@
// Copyright (c) 2019 Google LLC
//
// 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/transformation_add_type_vector.h"
#include "test/fuzz/fuzz_test_util.h"
namespace spvtools {
namespace fuzz {
namespace {
TEST(TransformationAddTypeVectorTest, BasicTest) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeInt 32 1
%8 = OpTypeInt 32 0
%9 = OpTypeBool
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_4;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
// Id already in use
ASSERT_FALSE(TransformationAddTypeVector(4, 6, 2).IsApplicable(context.get(),
fact_manager));
// %1 is not a type
ASSERT_FALSE(TransformationAddTypeVector(100, 1, 2).IsApplicable(
context.get(), fact_manager));
TransformationAddTypeVector transformations[] = {
// %100 = OpTypeVector %6 2
TransformationAddTypeVector(100, 6, 2),
// %101 = OpTypeVector %7 3
TransformationAddTypeVector(101, 7, 3),
// %102 = OpTypeVector %8 4
TransformationAddTypeVector(102, 8, 4),
// %103 = OpTypeVector %9 2
TransformationAddTypeVector(103, 9, 2)};
for (auto& transformation : transformations) {
ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
transformation.Apply(context.get(), &fact_manager);
}
ASSERT_TRUE(IsValid(env, context.get()));
std::string after_transformation = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
%7 = OpTypeInt 32 1
%8 = OpTypeInt 32 0
%9 = OpTypeBool
%100 = OpTypeVector %6 2
%101 = OpTypeVector %7 3
%102 = OpTypeVector %8 4
%103 = OpTypeVector %9 2
%4 = OpFunction %2 None %3
%5 = OpLabel
OpReturn
OpFunctionEnd
)";
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
} // namespace
} // namespace fuzz
} // namespace spvtools