mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-22 11:40:05 +00:00
parent
522561619a
commit
2f69ea849a
@ -49,7 +49,6 @@ if(SPIRV_BUILD_FUZZER)
|
||||
fuzzer_pass_add_local_variables.h
|
||||
fuzzer_pass_add_no_contraction_decorations.h
|
||||
fuzzer_pass_add_stores.h
|
||||
fuzzer_pass_add_useful_constructs.h
|
||||
fuzzer_pass_adjust_branch_weights.h
|
||||
fuzzer_pass_adjust_function_controls.h
|
||||
fuzzer_pass_adjust_loop_controls.h
|
||||
@ -146,7 +145,6 @@ if(SPIRV_BUILD_FUZZER)
|
||||
fuzzer_pass_add_local_variables.cpp
|
||||
fuzzer_pass_add_no_contraction_decorations.cpp
|
||||
fuzzer_pass_add_stores.cpp
|
||||
fuzzer_pass_add_useful_constructs.cpp
|
||||
fuzzer_pass_adjust_branch_weights.cpp
|
||||
fuzzer_pass_adjust_function_controls.cpp
|
||||
fuzzer_pass_adjust_loop_controls.cpp
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "source/fuzz/fuzzer_pass_add_local_variables.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_no_contraction_decorations.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_stores.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_useful_constructs.h"
|
||||
#include "source/fuzz/fuzzer_pass_adjust_branch_weights.h"
|
||||
#include "source/fuzz/fuzzer_pass_adjust_function_controls.h"
|
||||
#include "source/fuzz/fuzzer_pass_adjust_loop_controls.h"
|
||||
@ -187,16 +186,6 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run(
|
||||
TransformationContext transformation_context(&fact_manager,
|
||||
impl_->validator_options);
|
||||
|
||||
// Add some essential ingredients to the module if they are not already
|
||||
// present, such as boolean constants.
|
||||
FuzzerPassAddUsefulConstructs add_useful_constructs(
|
||||
ir_context.get(), &transformation_context, &fuzzer_context,
|
||||
transformation_sequence_out);
|
||||
if (!impl_->ApplyPassAndCheckValidity(&add_useful_constructs, *ir_context,
|
||||
tools)) {
|
||||
return Fuzzer::FuzzerResultStatus::kFuzzerPassLedToInvalidModule;
|
||||
}
|
||||
|
||||
// Apply some semantics-preserving passes.
|
||||
std::vector<std::unique_ptr<FuzzerPass>> passes;
|
||||
while (passes.empty()) {
|
||||
|
@ -319,6 +319,35 @@ uint32_t FuzzerPass::FindOrCreateBoolConstant(bool value) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t FuzzerPass::FindOrCreateConstant(const std::vector<uint32_t>& words,
|
||||
uint32_t type_id) {
|
||||
assert(type_id && "Constant's type id can't be 0.");
|
||||
|
||||
const auto* type = GetIRContext()->get_type_mgr()->GetType(type_id);
|
||||
assert(type && "Type does not exist.");
|
||||
|
||||
if (type->AsBool()) {
|
||||
assert(words.size() == 1);
|
||||
return FindOrCreateBoolConstant(words[0]);
|
||||
} else if (const auto* integer = type->AsInteger()) {
|
||||
assert(integer->width() == 32 && words.size() == 1 &&
|
||||
"Integer must have 32-bit width");
|
||||
return FindOrCreate32BitIntegerConstant(words[0], integer->IsSigned());
|
||||
} else if (const auto* floating = type->AsFloat()) {
|
||||
// Assertions are not evaluated in release builds so |floating|
|
||||
// variable will be unused.
|
||||
(void)floating;
|
||||
assert(floating->width() == 32 && words.size() == 1 &&
|
||||
"Floating point number must have 32-bit width");
|
||||
return FindOrCreate32BitFloatConstant(words[0]);
|
||||
}
|
||||
|
||||
// This assertion will fail in debug build but not in release build
|
||||
// so we return 0 to make compiler happy.
|
||||
assert(false && "Constant type is not supported");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t FuzzerPass::FindOrCreateGlobalUndef(uint32_t type_id) {
|
||||
for (auto& inst : GetIRContext()->types_values()) {
|
||||
if (inst.opcode() == SpvOpUndef && inst.type_id() == type_id) {
|
||||
|
@ -164,6 +164,14 @@ class FuzzerPass {
|
||||
// type do not exist, transformations are applied to add them.
|
||||
uint32_t FindOrCreateBoolConstant(bool value);
|
||||
|
||||
// Returns the id of an OpConstant instruction of type with |type_id|
|
||||
// that consists of |words|. If that instruction doesn't exist,
|
||||
// transformations are applied to add it. |type_id| must be a valid
|
||||
// result id of either scalar or boolean OpType* instruction that exists
|
||||
// in the module.
|
||||
uint32_t FindOrCreateConstant(const std::vector<uint32_t>& words,
|
||||
uint32_t type_id);
|
||||
|
||||
// Returns the result id of an instruction of the form:
|
||||
// %id = OpUndef %|type_id|
|
||||
// If no such instruction exists, a transformation is applied to add it.
|
||||
|
@ -41,6 +41,12 @@ void FuzzerPassAddDeadBlocks::Apply() {
|
||||
GetFuzzerContext()->GetChanceOfAddingDeadBlock())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make sure the module contains a boolean constant equal to
|
||||
// |condition_value|.
|
||||
bool condition_value = GetFuzzerContext()->ChooseEven();
|
||||
FindOrCreateBoolConstant(condition_value);
|
||||
|
||||
// We speculatively create a transformation, and then apply it (below) if
|
||||
// it turns out to be applicable. This avoids duplicating the logic for
|
||||
// applicability checking.
|
||||
@ -48,8 +54,7 @@ void FuzzerPassAddDeadBlocks::Apply() {
|
||||
// It means that fresh ids for transformations that turn out not to be
|
||||
// applicable end up being unused.
|
||||
candidate_transformations.emplace_back(TransformationAddDeadBlock(
|
||||
GetFuzzerContext()->GetFreshId(), block.id(),
|
||||
GetFuzzerContext()->ChooseEven()));
|
||||
GetFuzzerContext()->GetFreshId(), block.id(), condition_value));
|
||||
}
|
||||
}
|
||||
// Apply all those transformations that are in fact applicable.
|
||||
|
@ -77,9 +77,13 @@ void FuzzerPassAddDeadBreaks::Apply() {
|
||||
});
|
||||
}
|
||||
|
||||
// Make sure the module has a required boolean constant to be used in
|
||||
// OpBranchConditional instruction.
|
||||
auto break_condition = GetFuzzerContext()->ChooseEven();
|
||||
FindOrCreateBoolConstant(break_condition);
|
||||
|
||||
auto candidate_transformation = TransformationAddDeadBreak(
|
||||
block.id(), merge_block->id(), GetFuzzerContext()->ChooseEven(),
|
||||
std::move(phi_ids));
|
||||
block.id(), merge_block->id(), break_condition, std::move(phi_ids));
|
||||
if (candidate_transformation.IsApplicable(
|
||||
GetIRContext(), *GetTransformationContext())) {
|
||||
// Only consider a transformation as a candidate if it is applicable.
|
||||
|
@ -68,11 +68,16 @@ void FuzzerPassAddDeadContinues::Apply() {
|
||||
});
|
||||
}
|
||||
|
||||
// Make sure the module contains a boolean constant equal to
|
||||
// |condition_value|.
|
||||
bool condition_value = GetFuzzerContext()->ChooseEven();
|
||||
FindOrCreateBoolConstant(condition_value);
|
||||
|
||||
// Make a transformation to add a dead continue from this node; if the
|
||||
// node turns out to be inappropriate (e.g. by not being in a loop) the
|
||||
// precondition for the transformation will fail and it will be ignored.
|
||||
auto candidate_transformation = TransformationAddDeadContinue(
|
||||
block.id(), GetFuzzerContext()->ChooseEven(), std::move(phi_ids));
|
||||
block.id(), condition_value, std::move(phi_ids));
|
||||
// Probabilistically decide whether to apply the transformation in the
|
||||
// case that it is applicable.
|
||||
if (candidate_transformation.IsApplicable(GetIRContext(),
|
||||
|
@ -1,222 +0,0 @@
|
||||
// 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, TransformationContext* transformation_context,
|
||||
FuzzerContext* fuzzer_context,
|
||||
protobufs::TransformationSequence* transformations)
|
||||
: FuzzerPass(ir_context, transformation_context, 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(),
|
||||
*GetTransformationContext()) &&
|
||||
"Should be applicable by construction.");
|
||||
add_constant_int.Apply(GetIRContext(), GetTransformationContext());
|
||||
*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(),
|
||||
*GetTransformationContext()) &&
|
||||
"Should be applicable by construction.");
|
||||
add_constant_float.Apply(GetIRContext(), GetTransformationContext());
|
||||
*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(),
|
||||
*GetTransformationContext()) &&
|
||||
"Should be applicable by construction.");
|
||||
add_type_boolean.Apply(GetIRContext(), GetTransformationContext());
|
||||
*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(),
|
||||
*GetTransformationContext()) &&
|
||||
"Should be applicable by construction.");
|
||||
add_type_int.Apply(GetIRContext(), GetTransformationContext());
|
||||
*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(),
|
||||
*GetTransformationContext()) &&
|
||||
"Should be applicable by construction.");
|
||||
add_type_float.Apply(GetIRContext(), GetTransformationContext());
|
||||
*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(),
|
||||
*GetTransformationContext()) &&
|
||||
"Should be applicable by construction.");
|
||||
add_constant_boolean.Apply(GetIRContext(), GetTransformationContext());
|
||||
*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 : GetTransformationContext()
|
||||
->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(),
|
||||
*GetTransformationContext()) &&
|
||||
"Should be applicable by construction.");
|
||||
add_pointer.Apply(GetIRContext(), GetTransformationContext());
|
||||
*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
|
@ -1,46 +0,0 @@
|
||||
// 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_FUZZER_PASS_ADD_USEFUL_CONSTRUCTS_
|
||||
#define SOURCE_FUZZ_FUZZER_PASS_ADD_USEFUL_CONSTRUCTS_
|
||||
|
||||
#include "source/fuzz/fuzzer_pass.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
// An initial pass for adding useful ingredients to the module, such as boolean
|
||||
// constants, if they are not present.
|
||||
class FuzzerPassAddUsefulConstructs : public FuzzerPass {
|
||||
public:
|
||||
FuzzerPassAddUsefulConstructs(
|
||||
opt::IRContext* ir_context, TransformationContext* transformation_context,
|
||||
FuzzerContext* fuzzer_context,
|
||||
protobufs::TransformationSequence* transformations);
|
||||
|
||||
~FuzzerPassAddUsefulConstructs() override;
|
||||
|
||||
void Apply() override;
|
||||
|
||||
private:
|
||||
void MaybeAddIntConstant(uint32_t width, bool is_signed,
|
||||
std::vector<uint32_t> data) const;
|
||||
|
||||
void MaybeAddFloatConstant(uint32_t width, std::vector<uint32_t> data) const;
|
||||
};
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SOURCE_FUZZ_FUZZER_PASS_ADD_USEFUL_CONSTRUCTS_
|
@ -14,11 +14,14 @@
|
||||
|
||||
#include "source/fuzz/fuzzer_pass_obfuscate_constants.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "source/fuzz/fuzzer_util.h"
|
||||
#include "source/fuzz/instruction_descriptor.h"
|
||||
#include "source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h"
|
||||
#include "source/fuzz/transformation_replace_constant_with_uniform.h"
|
||||
#include "source/fuzz/uniform_buffer_element_descriptor.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
|
||||
namespace spvtools {
|
||||
@ -240,6 +243,29 @@ void FuzzerPassObfuscateConstants::
|
||||
first_constant_is_larger);
|
||||
}
|
||||
|
||||
std::vector<std::vector<uint32_t>>
|
||||
FuzzerPassObfuscateConstants::GetConstantWordsFromUniformsForType(
|
||||
uint32_t type_id) {
|
||||
assert(type_id && "Type id can't be 0");
|
||||
std::vector<std::vector<uint32_t>> result;
|
||||
|
||||
for (const auto& facts_and_types : GetTransformationContext()
|
||||
->GetFactManager()
|
||||
->GetConstantUniformFactsAndTypes()) {
|
||||
if (facts_and_types.second != type_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> words(facts_and_types.first.constant_word().begin(),
|
||||
facts_and_types.first.constant_word().end());
|
||||
if (std::find(result.begin(), result.end(), words) == result.end()) {
|
||||
result.push_back(std::move(words));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void FuzzerPassObfuscateConstants::ObfuscateBoolConstant(
|
||||
uint32_t depth, const protobufs::IdUseDescriptor& constant_use) {
|
||||
// We want to replace the boolean constant use with a binary expression over
|
||||
@ -258,11 +284,9 @@ void FuzzerPassObfuscateConstants::ObfuscateBoolConstant(
|
||||
auto chosen_type_id =
|
||||
available_types_with_uniforms[GetFuzzerContext()->RandomIndex(
|
||||
available_types_with_uniforms)];
|
||||
auto available_constants = GetTransformationContext()
|
||||
->GetFactManager()
|
||||
->GetConstantsAvailableFromUniformsForType(
|
||||
GetIRContext(), chosen_type_id);
|
||||
if (available_constants.size() == 1) {
|
||||
auto available_constant_words =
|
||||
GetConstantWordsFromUniformsForType(chosen_type_id);
|
||||
if (available_constant_words.size() == 1) {
|
||||
// TODO(afd): for now we only obfuscate a boolean if there are at least
|
||||
// two constants available from uniforms, so that we can do a
|
||||
// comparison between them. It would be good to be able to do the
|
||||
@ -271,18 +295,25 @@ void FuzzerPassObfuscateConstants::ObfuscateBoolConstant(
|
||||
return;
|
||||
}
|
||||
|
||||
assert(!available_constant_words.empty() &&
|
||||
"There exists a fact but no constants - impossible");
|
||||
|
||||
// We know we have at least two known-to-be-constant uniforms of the chosen
|
||||
// type. Pick one of them at random.
|
||||
auto constant_index_1 = GetFuzzerContext()->RandomIndex(available_constants);
|
||||
auto constant_index_1 =
|
||||
GetFuzzerContext()->RandomIndex(available_constant_words);
|
||||
uint32_t constant_index_2;
|
||||
|
||||
// Now choose another one distinct from the first one.
|
||||
do {
|
||||
constant_index_2 = GetFuzzerContext()->RandomIndex(available_constants);
|
||||
constant_index_2 =
|
||||
GetFuzzerContext()->RandomIndex(available_constant_words);
|
||||
} while (constant_index_1 == constant_index_2);
|
||||
|
||||
auto constant_id_1 = available_constants[constant_index_1];
|
||||
auto constant_id_2 = available_constants[constant_index_2];
|
||||
auto constant_id_1 = FindOrCreateConstant(
|
||||
available_constant_words[constant_index_1], chosen_type_id);
|
||||
auto constant_id_2 = FindOrCreateConstant(
|
||||
available_constant_words[constant_index_2], chosen_type_id);
|
||||
|
||||
assert(constant_id_1 != 0 && constant_id_2 != 0 &&
|
||||
"We should not find an available constant with an id of 0.");
|
||||
@ -324,18 +355,39 @@ void FuzzerPassObfuscateConstants::ObfuscateScalarConstant(
|
||||
}
|
||||
|
||||
// Choose a random available uniform known to be equal to the constant.
|
||||
protobufs::UniformBufferElementDescriptor uniform_descriptor =
|
||||
const auto& uniform_descriptor =
|
||||
uniform_descriptors[GetFuzzerContext()->RandomIndex(uniform_descriptors)];
|
||||
|
||||
// Make sure the module has OpConstant instructions for each index used to
|
||||
// access a uniform.
|
||||
for (auto index : uniform_descriptor.index()) {
|
||||
FindOrCreate32BitIntegerConstant(index, true);
|
||||
}
|
||||
|
||||
// Make sure the module has OpTypePointer that points to the element type of
|
||||
// the uniform.
|
||||
const auto* uniform_variable_instr =
|
||||
FindUniformVariable(uniform_descriptor, GetIRContext(), true);
|
||||
assert(uniform_variable_instr &&
|
||||
"Uniform variable does not exist or not unique.");
|
||||
|
||||
const auto* uniform_variable_type_intr =
|
||||
GetIRContext()->get_def_use_mgr()->GetDef(
|
||||
uniform_variable_instr->type_id());
|
||||
assert(uniform_variable_type_intr && "Uniform variable has invalid type");
|
||||
|
||||
auto element_type_id = fuzzerutil::WalkCompositeTypeIndices(
|
||||
GetIRContext(), uniform_variable_type_intr->GetSingleWordInOperand(1),
|
||||
uniform_descriptor.index());
|
||||
assert(element_type_id && "Type of uniform variable is invalid");
|
||||
|
||||
FindOrCreatePointerType(element_type_id, SpvStorageClassUniform);
|
||||
|
||||
// Create, apply and record a transformation to replace the constant use with
|
||||
// the result of a load from the chosen uniform.
|
||||
auto transformation = TransformationReplaceConstantWithUniform(
|
||||
ApplyTransformation(TransformationReplaceConstantWithUniform(
|
||||
constant_use, uniform_descriptor, GetFuzzerContext()->GetFreshId(),
|
||||
GetFuzzerContext()->GetFreshId());
|
||||
// Transformation should be applicable by construction.
|
||||
assert(
|
||||
transformation.IsApplicable(GetIRContext(), *GetTransformationContext()));
|
||||
transformation.Apply(GetIRContext(), GetTransformationContext());
|
||||
*GetTransformations()->add_transformation() = transformation.ToMessage();
|
||||
GetFuzzerContext()->GetFreshId()));
|
||||
}
|
||||
|
||||
void FuzzerPassObfuscateConstants::ObfuscateConstant(
|
||||
|
@ -99,6 +99,11 @@ class FuzzerPassObfuscateConstants : public FuzzerPass {
|
||||
uint32_t base_instruction_result_id,
|
||||
const std::map<SpvOp, uint32_t>& skipped_opcode_count,
|
||||
std::vector<protobufs::IdUseDescriptor>* constant_uses);
|
||||
|
||||
// Returns a vector of unique words that denote constants. Every such constant
|
||||
// is used in |FactConstantUniform| and has type with id equal to |type_id|.
|
||||
std::vector<std::vector<uint32_t>> GetConstantWordsFromUniformsForType(
|
||||
uint32_t type_id);
|
||||
};
|
||||
|
||||
} // namespace fuzz
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
|
||||
#include "source/fuzz/transformation_context.h"
|
||||
#include "source/opt/basic_block.h"
|
||||
#include "source/opt/instruction.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
|
@ -21,7 +21,6 @@ if (${SPIRV_BUILD_FUZZER})
|
||||
equivalence_relation_test.cpp
|
||||
fact_manager_test.cpp
|
||||
fuzz_test_util.cpp
|
||||
fuzzer_pass_add_useful_constructs_test.cpp
|
||||
fuzzer_pass_construct_composites_test.cpp
|
||||
fuzzer_pass_donate_modules_test.cpp
|
||||
instruction_descriptor_test.cpp
|
||||
|
@ -1,401 +0,0 @@
|
||||
// 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/pseudo_random_generator.h"
|
||||
#include "source/fuzz/uniform_buffer_element_descriptor.h"
|
||||
#include "test/fuzz/fuzz_test_util.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
namespace {
|
||||
|
||||
bool AddFactHelper(
|
||||
FactManager* fact_manager, opt::IRContext* context, uint32_t word,
|
||||
const protobufs::UniformBufferElementDescriptor& descriptor) {
|
||||
protobufs::FactConstantUniform constant_uniform_fact;
|
||||
constant_uniform_fact.add_constant_word(word);
|
||||
*constant_uniform_fact.mutable_uniform_buffer_element_descriptor() =
|
||||
descriptor;
|
||||
protobufs::Fact fact;
|
||||
*fact.mutable_constant_uniform_fact() = constant_uniform_fact;
|
||||
return fact_manager->AddFact(fact, context);
|
||||
}
|
||||
|
||||
TEST(FuzzerPassAddUsefulConstructsTest, CheckBasicStuffIsAdded) {
|
||||
// The SPIR-V came from the following empty GLSL shader:
|
||||
//
|
||||
// #version 450
|
||||
//
|
||||
// void main()
|
||||
// {
|
||||
// }
|
||||
|
||||
std::string shader = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %4 "main"
|
||||
OpExecutionMode %4 OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %4 "main"
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||
const auto consumer = nullptr;
|
||||
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
FactManager fact_manager;
|
||||
spvtools::ValidatorOptions validator_options;
|
||||
TransformationContext transformation_context(&fact_manager,
|
||||
validator_options);
|
||||
|
||||
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0).get(), 100);
|
||||
protobufs::TransformationSequence transformation_sequence;
|
||||
|
||||
FuzzerPassAddUsefulConstructs pass(context.get(), &transformation_context,
|
||||
&fuzzer_context, &transformation_sequence);
|
||||
pass.Apply();
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
std::string after = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %4 "main"
|
||||
OpExecutionMode %4 OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %4 "main"
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%100 = OpTypeBool
|
||||
%101 = OpTypeInt 32 1
|
||||
%102 = OpTypeInt 32 0
|
||||
%103 = OpTypeFloat 32
|
||||
%104 = OpConstantTrue %100
|
||||
%105 = OpConstantFalse %100
|
||||
%106 = OpConstant %101 0
|
||||
%107 = OpConstant %101 1
|
||||
%108 = OpConstant %102 0
|
||||
%109 = OpConstant %102 1
|
||||
%110 = OpConstant %103 0
|
||||
%111 = OpConstant %103 1
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
ASSERT_TRUE(IsEqual(env, after, context.get()));
|
||||
}
|
||||
|
||||
TEST(FuzzerPassAddUsefulConstructsTest,
|
||||
CheckTypesIndicesAndConstantsAddedForUniformFacts) {
|
||||
// The SPIR-V came from the following GLSL shader:
|
||||
//
|
||||
// #version 450
|
||||
//
|
||||
// struct S {
|
||||
// int x;
|
||||
// float y;
|
||||
// int z;
|
||||
// int w;
|
||||
// };
|
||||
//
|
||||
// uniform buf {
|
||||
// S s;
|
||||
// uint w[10];
|
||||
// };
|
||||
//
|
||||
// void main() {
|
||||
// }
|
||||
|
||||
std::string shader = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %4 "main"
|
||||
OpExecutionMode %4 OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %4 "main"
|
||||
OpName %8 "S"
|
||||
OpMemberName %8 0 "x"
|
||||
OpMemberName %8 1 "y"
|
||||
OpMemberName %8 2 "z"
|
||||
OpMemberName %8 3 "w"
|
||||
OpName %12 "buf"
|
||||
OpMemberName %12 0 "s"
|
||||
OpMemberName %12 1 "w"
|
||||
OpName %14 ""
|
||||
OpMemberDecorate %8 0 Offset 0
|
||||
OpMemberDecorate %8 1 Offset 4
|
||||
OpMemberDecorate %8 2 Offset 8
|
||||
OpMemberDecorate %8 3 Offset 12
|
||||
OpDecorate %11 ArrayStride 16
|
||||
OpMemberDecorate %12 0 Offset 0
|
||||
OpMemberDecorate %12 1 Offset 16
|
||||
OpDecorate %12 Block
|
||||
OpDecorate %14 DescriptorSet 0
|
||||
OpDecorate %14 Binding 0
|
||||
%2 = OpTypeVoid
|
||||
%3 = OpTypeFunction %2
|
||||
%6 = OpTypeInt 32 1
|
||||
%7 = OpTypeFloat 32
|
||||
%8 = OpTypeStruct %6 %7 %6 %6
|
||||
%9 = OpTypeInt 32 0
|
||||
%10 = OpConstant %9 10
|
||||
%11 = OpTypeArray %9 %10
|
||||
%12 = OpTypeStruct %8 %11
|
||||
%13 = OpTypePointer Uniform %12
|
||||
%14 = OpVariable %13 Uniform
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
||||
const auto consumer = nullptr;
|
||||
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
FactManager fact_manager;
|
||||
spvtools::ValidatorOptions validator_options;
|
||||
TransformationContext transformation_context(&fact_manager,
|
||||
validator_options);
|
||||
|
||||
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0).get(), 100);
|
||||
protobufs::TransformationSequence transformation_sequence;
|
||||
|
||||
// Add some uniform facts.
|
||||
|
||||
// buf.s.x == 200
|
||||
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 200,
|
||||
MakeUniformBufferElementDescriptor(0, 0, {0, 0})));
|
||||
|
||||
// buf.s.y == 0.5
|
||||
const float float_value = 0.5;
|
||||
uint32_t float_value_as_uint;
|
||||
memcpy(&float_value_as_uint, &float_value, sizeof(float_value));
|
||||
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), float_value_as_uint,
|
||||
MakeUniformBufferElementDescriptor(0, 0, {0, 1})));
|
||||
|
||||
// buf.s.z == 300
|
||||
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 300,
|
||||
MakeUniformBufferElementDescriptor(0, 0, {0, 2})));
|
||||
|
||||
// buf.s.w == 400
|
||||
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 400,
|
||||
MakeUniformBufferElementDescriptor(0, 0, {0, 3})));
|
||||
|
||||
// buf.w[6] = 22
|
||||
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 22,
|
||||
MakeUniformBufferElementDescriptor(0, 0, {1, 6})));
|
||||
|
||||
// buf.w[8] = 23
|
||||
ASSERT_TRUE(AddFactHelper(&fact_manager, context.get(), 23,
|
||||
MakeUniformBufferElementDescriptor(0, 0, {1, 8})));
|
||||
|
||||
// Assert some things about the module that are not true prior to adding the
|
||||
// pass
|
||||
|
||||
{
|
||||
// No uniform int pointer
|
||||
opt::analysis::Integer temp_type_signed_int(32, true);
|
||||
opt::analysis::Integer* registered_type_signed_int =
|
||||
context->get_type_mgr()
|
||||
->GetRegisteredType(&temp_type_signed_int)
|
||||
->AsInteger();
|
||||
opt::analysis::Pointer type_pointer_uniform_signed_int(
|
||||
registered_type_signed_int, SpvStorageClassUniform);
|
||||
ASSERT_EQ(0,
|
||||
context->get_type_mgr()->GetId(&type_pointer_uniform_signed_int));
|
||||
|
||||
// No uniform uint pointer
|
||||
opt::analysis::Integer temp_type_unsigned_int(32, false);
|
||||
opt::analysis::Integer* registered_type_unsigned_int =
|
||||
context->get_type_mgr()
|
||||
->GetRegisteredType(&temp_type_unsigned_int)
|
||||
->AsInteger();
|
||||
opt::analysis::Pointer type_pointer_uniform_unsigned_int(
|
||||
registered_type_unsigned_int, SpvStorageClassUniform);
|
||||
ASSERT_EQ(
|
||||
0, context->get_type_mgr()->GetId(&type_pointer_uniform_unsigned_int));
|
||||
|
||||
// No uniform float pointer
|
||||
opt::analysis::Float temp_type_float(32);
|
||||
opt::analysis::Float* registered_type_float =
|
||||
context->get_type_mgr()->GetRegisteredType(&temp_type_float)->AsFloat();
|
||||
opt::analysis::Pointer type_pointer_uniform_float(registered_type_float,
|
||||
SpvStorageClassUniform);
|
||||
ASSERT_EQ(0, context->get_type_mgr()->GetId(&type_pointer_uniform_float));
|
||||
|
||||
// No int constants 200, 300 nor 400
|
||||
opt::analysis::IntConstant int_constant_200(registered_type_signed_int,
|
||||
{200});
|
||||
opt::analysis::IntConstant int_constant_300(registered_type_signed_int,
|
||||
{300});
|
||||
opt::analysis::IntConstant int_constant_400(registered_type_signed_int,
|
||||
{400});
|
||||
ASSERT_EQ(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_200));
|
||||
ASSERT_EQ(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_300));
|
||||
ASSERT_EQ(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_400));
|
||||
|
||||
// No float constant 0.5
|
||||
opt::analysis::FloatConstant float_constant_zero_point_five(
|
||||
registered_type_float, {float_value_as_uint});
|
||||
ASSERT_EQ(nullptr, context->get_constant_mgr()->FindConstant(
|
||||
&float_constant_zero_point_five));
|
||||
|
||||
// No uint constant 22
|
||||
opt::analysis::IntConstant uint_constant_22(registered_type_unsigned_int,
|
||||
{22});
|
||||
ASSERT_EQ(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&uint_constant_22));
|
||||
|
||||
// No uint constant 23
|
||||
opt::analysis::IntConstant uint_constant_23(registered_type_unsigned_int,
|
||||
{23});
|
||||
ASSERT_EQ(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&uint_constant_23));
|
||||
|
||||
// No int constants 0, 1, 2, 3, 6, 8
|
||||
opt::analysis::IntConstant int_constant_0(registered_type_signed_int, {0});
|
||||
opt::analysis::IntConstant int_constant_1(registered_type_signed_int, {1});
|
||||
opt::analysis::IntConstant int_constant_2(registered_type_signed_int, {2});
|
||||
opt::analysis::IntConstant int_constant_3(registered_type_signed_int, {3});
|
||||
opt::analysis::IntConstant int_constant_6(registered_type_signed_int, {6});
|
||||
opt::analysis::IntConstant int_constant_8(registered_type_signed_int, {8});
|
||||
ASSERT_EQ(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_0));
|
||||
ASSERT_EQ(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_1));
|
||||
ASSERT_EQ(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_2));
|
||||
ASSERT_EQ(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_3));
|
||||
ASSERT_EQ(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_6));
|
||||
ASSERT_EQ(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_8));
|
||||
}
|
||||
|
||||
FuzzerPassAddUsefulConstructs pass(context.get(), &transformation_context,
|
||||
&fuzzer_context, &transformation_sequence);
|
||||
pass.Apply();
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
// Now assert some things about the module that should be true following the
|
||||
// pass.
|
||||
|
||||
// We reconstruct all necessary types and constants to guard against the type
|
||||
// and constant managers for the module having been invalidated.
|
||||
|
||||
{
|
||||
// Uniform int pointer now present
|
||||
opt::analysis::Integer temp_type_signed_int(32, true);
|
||||
opt::analysis::Integer* registered_type_signed_int =
|
||||
context->get_type_mgr()
|
||||
->GetRegisteredType(&temp_type_signed_int)
|
||||
->AsInteger();
|
||||
opt::analysis::Pointer type_pointer_uniform_signed_int(
|
||||
registered_type_signed_int, SpvStorageClassUniform);
|
||||
ASSERT_NE(0,
|
||||
context->get_type_mgr()->GetId(&type_pointer_uniform_signed_int));
|
||||
|
||||
// Uniform uint pointer now present
|
||||
opt::analysis::Integer temp_type_unsigned_int(32, false);
|
||||
opt::analysis::Integer* registered_type_unsigned_int =
|
||||
context->get_type_mgr()
|
||||
->GetRegisteredType(&temp_type_unsigned_int)
|
||||
->AsInteger();
|
||||
opt::analysis::Pointer type_pointer_uniform_unsigned_int(
|
||||
registered_type_unsigned_int, SpvStorageClassUniform);
|
||||
ASSERT_NE(
|
||||
0, context->get_type_mgr()->GetId(&type_pointer_uniform_unsigned_int));
|
||||
|
||||
// Uniform float pointer now present
|
||||
opt::analysis::Float temp_type_float(32);
|
||||
opt::analysis::Float* registered_type_float =
|
||||
context->get_type_mgr()->GetRegisteredType(&temp_type_float)->AsFloat();
|
||||
opt::analysis::Pointer type_pointer_uniform_float(registered_type_float,
|
||||
SpvStorageClassUniform);
|
||||
ASSERT_NE(0, context->get_type_mgr()->GetId(&type_pointer_uniform_float));
|
||||
|
||||
// int constants 200, 300, 400 now present
|
||||
opt::analysis::IntConstant int_constant_200(registered_type_signed_int,
|
||||
{200});
|
||||
opt::analysis::IntConstant int_constant_300(registered_type_signed_int,
|
||||
{300});
|
||||
opt::analysis::IntConstant int_constant_400(registered_type_signed_int,
|
||||
{400});
|
||||
ASSERT_NE(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_200));
|
||||
ASSERT_NE(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_300));
|
||||
ASSERT_NE(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_400));
|
||||
|
||||
// float constant 0.5 now present
|
||||
opt::analysis::FloatConstant float_constant_zero_point_five(
|
||||
registered_type_float, {float_value_as_uint});
|
||||
ASSERT_NE(nullptr, context->get_constant_mgr()->FindConstant(
|
||||
&float_constant_zero_point_five));
|
||||
|
||||
// uint constant 22 now present
|
||||
opt::analysis::IntConstant uint_constant_22(registered_type_unsigned_int,
|
||||
{22});
|
||||
ASSERT_NE(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&uint_constant_22));
|
||||
|
||||
// uint constant 23 now present
|
||||
opt::analysis::IntConstant uint_constant_23(registered_type_unsigned_int,
|
||||
{23});
|
||||
ASSERT_NE(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&uint_constant_23));
|
||||
|
||||
// int constants 0, 1, 2, 3, 6, 8 now present
|
||||
opt::analysis::IntConstant int_constant_0(registered_type_signed_int, {0});
|
||||
opt::analysis::IntConstant int_constant_1(registered_type_signed_int, {1});
|
||||
opt::analysis::IntConstant int_constant_2(registered_type_signed_int, {2});
|
||||
opt::analysis::IntConstant int_constant_3(registered_type_signed_int, {3});
|
||||
opt::analysis::IntConstant int_constant_6(registered_type_signed_int, {6});
|
||||
opt::analysis::IntConstant int_constant_8(registered_type_signed_int, {8});
|
||||
ASSERT_NE(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_0));
|
||||
ASSERT_NE(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_1));
|
||||
ASSERT_NE(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_2));
|
||||
ASSERT_NE(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_3));
|
||||
ASSERT_NE(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_6));
|
||||
ASSERT_NE(nullptr,
|
||||
context->get_constant_mgr()->FindConstant(&int_constant_8));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
Loading…
Reference in New Issue
Block a user