| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214 |
- // 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/fuzzer_pass_add_useful_constructs.h"
- #include "source/fuzz/transformation_add_constant_boolean.h"
- #include "source/fuzz/transformation_add_constant_scalar.h"
- #include "source/fuzz/transformation_add_type_boolean.h"
- #include "source/fuzz/transformation_add_type_float.h"
- #include "source/fuzz/transformation_add_type_int.h"
- #include "source/fuzz/transformation_add_type_pointer.h"
- namespace spvtools {
- namespace fuzz {
- FuzzerPassAddUsefulConstructs::FuzzerPassAddUsefulConstructs(
- opt::IRContext* ir_context, FactManager* fact_manager,
- FuzzerContext* fuzzer_context,
- protobufs::TransformationSequence* transformations)
- : FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
- FuzzerPassAddUsefulConstructs::~FuzzerPassAddUsefulConstructs() = default;
- void FuzzerPassAddUsefulConstructs::MaybeAddIntConstant(
- uint32_t width, bool is_signed, std::vector<uint32_t> data) const {
- opt::analysis::Integer temp_int_type(width, is_signed);
- assert(GetIRContext()->get_type_mgr()->GetId(&temp_int_type) &&
- "int type should already be registered.");
- auto registered_int_type = GetIRContext()
- ->get_type_mgr()
- ->GetRegisteredType(&temp_int_type)
- ->AsInteger();
- auto int_type_id = GetIRContext()->get_type_mgr()->GetId(registered_int_type);
- assert(int_type_id &&
- "The relevant int type should have been added to the module already.");
- opt::analysis::IntConstant int_constant(registered_int_type, data);
- if (!GetIRContext()->get_constant_mgr()->FindConstant(&int_constant)) {
- TransformationAddConstantScalar add_constant_int =
- TransformationAddConstantScalar(GetFuzzerContext()->GetFreshId(),
- int_type_id, data);
- assert(add_constant_int.IsApplicable(GetIRContext(), *GetFactManager()) &&
- "Should be applicable by construction.");
- add_constant_int.Apply(GetIRContext(), GetFactManager());
- *GetTransformations()->add_transformation() = add_constant_int.ToMessage();
- }
- }
- void FuzzerPassAddUsefulConstructs::MaybeAddFloatConstant(
- uint32_t width, std::vector<uint32_t> data) const {
- opt::analysis::Float temp_float_type(width);
- assert(GetIRContext()->get_type_mgr()->GetId(&temp_float_type) &&
- "float type should already be registered.");
- auto registered_float_type = GetIRContext()
- ->get_type_mgr()
- ->GetRegisteredType(&temp_float_type)
- ->AsFloat();
- auto float_type_id =
- GetIRContext()->get_type_mgr()->GetId(registered_float_type);
- assert(
- float_type_id &&
- "The relevant float type should have been added to the module already.");
- opt::analysis::FloatConstant float_constant(registered_float_type, data);
- if (!GetIRContext()->get_constant_mgr()->FindConstant(&float_constant)) {
- TransformationAddConstantScalar add_constant_float =
- TransformationAddConstantScalar(GetFuzzerContext()->GetFreshId(),
- float_type_id, data);
- assert(add_constant_float.IsApplicable(GetIRContext(), *GetFactManager()) &&
- "Should be applicable by construction.");
- add_constant_float.Apply(GetIRContext(), GetFactManager());
- *GetTransformations()->add_transformation() =
- add_constant_float.ToMessage();
- }
- }
- void FuzzerPassAddUsefulConstructs::Apply() {
- {
- // Add boolean type if not present.
- opt::analysis::Bool temp_bool_type;
- if (!GetIRContext()->get_type_mgr()->GetId(&temp_bool_type)) {
- auto add_type_boolean =
- TransformationAddTypeBoolean(GetFuzzerContext()->GetFreshId());
- assert(add_type_boolean.IsApplicable(GetIRContext(), *GetFactManager()) &&
- "Should be applicable by construction.");
- add_type_boolean.Apply(GetIRContext(), GetFactManager());
- *GetTransformations()->add_transformation() =
- add_type_boolean.ToMessage();
- }
- }
- {
- // Add signed and unsigned 32-bit integer types if not present.
- for (auto is_signed : {true, false}) {
- opt::analysis::Integer temp_int_type(32, is_signed);
- if (!GetIRContext()->get_type_mgr()->GetId(&temp_int_type)) {
- TransformationAddTypeInt add_type_int = TransformationAddTypeInt(
- GetFuzzerContext()->GetFreshId(), 32, is_signed);
- assert(add_type_int.IsApplicable(GetIRContext(), *GetFactManager()) &&
- "Should be applicable by construction.");
- add_type_int.Apply(GetIRContext(), GetFactManager());
- *GetTransformations()->add_transformation() = add_type_int.ToMessage();
- }
- }
- }
- {
- // Add 32-bit float type if not present.
- opt::analysis::Float temp_float_type(32);
- if (!GetIRContext()->get_type_mgr()->GetId(&temp_float_type)) {
- TransformationAddTypeFloat add_type_float =
- TransformationAddTypeFloat(GetFuzzerContext()->GetFreshId(), 32);
- assert(add_type_float.IsApplicable(GetIRContext(), *GetFactManager()) &&
- "Should be applicable by construction.");
- add_type_float.Apply(GetIRContext(), GetFactManager());
- *GetTransformations()->add_transformation() = add_type_float.ToMessage();
- }
- }
- // Add boolean constants true and false if not present.
- opt::analysis::Bool temp_bool_type;
- auto bool_type = GetIRContext()
- ->get_type_mgr()
- ->GetRegisteredType(&temp_bool_type)
- ->AsBool();
- for (auto boolean_value : {true, false}) {
- // Add OpConstantTrue/False if not already there.
- opt::analysis::BoolConstant bool_constant(bool_type, boolean_value);
- if (!GetIRContext()->get_constant_mgr()->FindConstant(&bool_constant)) {
- TransformationAddConstantBoolean add_constant_boolean(
- GetFuzzerContext()->GetFreshId(), boolean_value);
- assert(add_constant_boolean.IsApplicable(GetIRContext(),
- *GetFactManager()) &&
- "Should be applicable by construction.");
- add_constant_boolean.Apply(GetIRContext(), GetFactManager());
- *GetTransformations()->add_transformation() =
- add_constant_boolean.ToMessage();
- }
- }
- // Add signed and unsigned 32-bit integer constants 0 and 1 if not present.
- for (auto is_signed : {true, false}) {
- for (auto value : {0u, 1u}) {
- MaybeAddIntConstant(32, is_signed, {value});
- }
- }
- // Add 32-bit float constants 0.0 and 1.0 if not present.
- uint32_t uint_data[2];
- float float_data[2] = {0.0, 1.0};
- memcpy(uint_data, float_data, sizeof(float_data));
- for (unsigned int& datum : uint_data) {
- MaybeAddFloatConstant(32, {datum});
- }
- // For every known-to-be-constant uniform, make sure we have instructions
- // declaring:
- // - a pointer type with uniform storage class, whose pointee type is the type
- // of the element
- // - a signed integer constant for each index required to access the element
- // - a constant for the constant value itself
- for (auto& fact_and_type_id :
- GetFactManager()->GetConstantUniformFactsAndTypes()) {
- uint32_t element_type_id = fact_and_type_id.second;
- assert(element_type_id);
- auto element_type =
- GetIRContext()->get_type_mgr()->GetType(element_type_id);
- assert(element_type &&
- "If the constant uniform fact is well-formed, the module must "
- "already have a declaration of the type for the uniform element.");
- opt::analysis::Pointer uniform_pointer(element_type,
- SpvStorageClassUniform);
- if (!GetIRContext()->get_type_mgr()->GetId(&uniform_pointer)) {
- auto add_pointer =
- TransformationAddTypePointer(GetFuzzerContext()->GetFreshId(),
- SpvStorageClassUniform, element_type_id);
- assert(add_pointer.IsApplicable(GetIRContext(), *GetFactManager()) &&
- "Should be applicable by construction.");
- add_pointer.Apply(GetIRContext(), GetFactManager());
- *GetTransformations()->add_transformation() = add_pointer.ToMessage();
- }
- std::vector<uint32_t> words;
- for (auto word : fact_and_type_id.first.constant_word()) {
- words.push_back(word);
- }
- // We get the element type again as the type manager may have been
- // invalidated since we last retrieved it.
- element_type = GetIRContext()->get_type_mgr()->GetType(element_type_id);
- if (element_type->AsInteger()) {
- MaybeAddIntConstant(element_type->AsInteger()->width(),
- element_type->AsInteger()->IsSigned(), words);
- } else {
- assert(element_type->AsFloat() &&
- "Known uniform values must be integer or floating-point.");
- MaybeAddFloatConstant(element_type->AsFloat()->width(), words);
- }
- for (auto index :
- fact_and_type_id.first.uniform_buffer_element_descriptor().index()) {
- MaybeAddIntConstant(32, true, {index});
- }
- }
- }
- } // namespace fuzz
- } // namespace spvtools
|