From add2440710cc825fff3c2f2f2d6e03f41010c19d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D1=80=D0=B0=D0=BD=D0=B8=D0=BC=D0=B8=D1=80=20=D0=9A?= =?UTF-8?q?=D0=B0=D1=80=D0=B0=D1=9F=D0=B8=D1=9B?= Date: Fri, 12 Jun 2020 22:06:54 -0700 Subject: [PATCH] Updated spirv-tools. --- .../include/generated/build-version.inc | 2 +- .../spirv-tools/source/fuzz/CMakeLists.txt | 2 + .../spirv-tools/source/fuzz/fact_manager.cpp | 6 +- ...zzer_pass_adjust_memory_operands_masks.cpp | 2 +- .../fuzz/fuzzer_pass_donate_modules.cpp | 33 +++++++- ...fuzzer_pass_push_ids_through_variables.cpp | 15 +++- .../spirv-tools/source/fuzz/fuzzer_util.cpp | 33 ++++++++ .../spirv-tools/source/fuzz/fuzzer_util.h | 11 +++ .../source/fuzz/protobufs/spvtoolsfuzz.proto | 19 +++++ .../source/fuzz/transformation.cpp | 4 + .../transformation_add_global_variable.cpp | 33 +------- .../fuzz/transformation_add_global_variable.h | 6 -- .../transformation_add_spec_constant_op.cpp | 84 +++++++++++++++++++ .../transformation_add_spec_constant_op.h | 60 +++++++++++++ ...ransformation_push_id_through_variable.cpp | 3 + ...ransformation_set_memory_operands_mask.cpp | 23 +++++ 16 files changed, 290 insertions(+), 46 deletions(-) create mode 100644 3rdparty/spirv-tools/source/fuzz/transformation_add_spec_constant_op.cpp create mode 100644 3rdparty/spirv-tools/source/fuzz/transformation_add_spec_constant_op.h diff --git a/3rdparty/spirv-tools/include/generated/build-version.inc b/3rdparty/spirv-tools/include/generated/build-version.inc index e78c3cbce..70abe50d9 100644 --- a/3rdparty/spirv-tools/include/generated/build-version.inc +++ b/3rdparty/spirv-tools/include/generated/build-version.inc @@ -1 +1 @@ -"v2020.4-dev", "SPIRV-Tools v2020.4-dev 3e4a8382b6d054cbd8f0a04a4f83c4350dd803ea" +"v2020.4-dev", "SPIRV-Tools v2020.4-dev 2cdcab3215d654e18c3b6d5f12bd94e7e64fb8b1" diff --git a/3rdparty/spirv-tools/source/fuzz/CMakeLists.txt b/3rdparty/spirv-tools/source/fuzz/CMakeLists.txt index 1fadd8fcb..efd82e431 100644 --- a/3rdparty/spirv-tools/source/fuzz/CMakeLists.txt +++ b/3rdparty/spirv-tools/source/fuzz/CMakeLists.txt @@ -90,6 +90,7 @@ if(SPIRV_BUILD_FUZZER) transformation_add_global_variable.h transformation_add_local_variable.h transformation_add_no_contraction_decoration.h + transformation_add_spec_constant_op.h transformation_add_type_array.h transformation_add_type_boolean.h transformation_add_type_float.h @@ -187,6 +188,7 @@ if(SPIRV_BUILD_FUZZER) transformation_add_global_variable.cpp transformation_add_local_variable.cpp transformation_add_no_contraction_decoration.cpp + transformation_add_spec_constant_op.cpp transformation_add_type_array.cpp transformation_add_type_boolean.cpp transformation_add_type_float.cpp diff --git a/3rdparty/spirv-tools/source/fuzz/fact_manager.cpp b/3rdparty/spirv-tools/source/fuzz/fact_manager.cpp index 0b41eeb59..2cbac9d8b 100644 --- a/3rdparty/spirv-tools/source/fuzz/fact_manager.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fact_manager.cpp @@ -813,8 +813,10 @@ void FactManager::DataSynonymAndIdEquationFacts::ComputeClosureOfFacts( struct DataDescriptorPairEquals { bool operator()(const DataDescriptorPair& first, const DataDescriptorPair& second) const { - return DataDescriptorEquals()(&first.first, &second.first) && - DataDescriptorEquals()(&first.second, &second.second); + return (DataDescriptorEquals()(&first.first, &second.first) && + DataDescriptorEquals()(&first.second, &second.second)) || + (DataDescriptorEquals()(&first.first, &second.second) && + DataDescriptorEquals()(&first.second, &second.first)); } }; diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp index 32f5ea5fb..68f0ca7e4 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp @@ -75,7 +75,7 @@ void FuzzerPassAdjustMemoryOperandsMasks::Apply() { *inst_it, mask_index); auto existing_mask = existing_mask_in_operand_index < inst_it->NumInOperands() - ? inst_it->GetSingleWordOperand( + ? inst_it->GetSingleWordInOperand( existing_mask_in_operand_index) : static_cast(SpvMemoryAccessMaskNone); diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.cpp index c06a928db..ffccd3c1a 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_donate_modules.cpp @@ -27,6 +27,7 @@ #include "source/fuzz/transformation_add_function.h" #include "source/fuzz/transformation_add_global_undef.h" #include "source/fuzz/transformation_add_global_variable.h" +#include "source/fuzz/transformation_add_spec_constant_op.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" @@ -413,14 +414,41 @@ void FuzzerPassDonateModules::HandleTypeOrValue( argument_type_ids)); } } break; + case SpvOpSpecConstantOp: { + new_result_id = GetFuzzerContext()->GetFreshId(); + auto type_id = original_id_to_donated_id->at(type_or_value.type_id()); + auto opcode = static_cast(type_or_value.GetSingleWordInOperand(0)); + + // Make sure we take into account |original_id_to_donated_id| when + // computing operands for OpSpecConstantOp. + opt::Instruction::OperandList operands; + for (uint32_t i = 1; i < type_or_value.NumInOperands(); ++i) { + const auto& operand = type_or_value.GetInOperand(i); + auto data = + operand.type == SPV_OPERAND_TYPE_ID + ? opt::Operand::OperandData{original_id_to_donated_id->at( + operand.words[0])} + : operand.words; + + operands.push_back({operand.type, std::move(data)}); + } + + ApplyTransformation(TransformationAddSpecConstantOp( + new_result_id, type_id, opcode, std::move(operands))); + } break; + case SpvOpSpecConstantTrue: + case SpvOpSpecConstantFalse: case SpvOpConstantTrue: case SpvOpConstantFalse: { // It is OK to have duplicate definitions of True and False, so add // these to the module, using a remapped Bool type. new_result_id = GetFuzzerContext()->GetFreshId(); - ApplyTransformation(TransformationAddConstantBoolean( - new_result_id, type_or_value.opcode() == SpvOpConstantTrue)); + auto value = type_or_value.opcode() == SpvOpConstantTrue || + type_or_value.opcode() == SpvOpSpecConstantTrue; + ApplyTransformation( + TransformationAddConstantBoolean(new_result_id, value)); } break; + case SpvOpSpecConstant: case SpvOpConstant: { // It is OK to have duplicate constant definitions, so add this to the // module using a remapped result type. @@ -433,6 +461,7 @@ void FuzzerPassDonateModules::HandleTypeOrValue( new_result_id, original_id_to_donated_id->at(type_or_value.type_id()), data_words)); } break; + case SpvOpSpecConstantComposite: case SpvOpConstantComposite: { assert(original_id_to_donated_id->count(type_or_value.type_id()) && "Composite types for which it is possible to create a constant " diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp index fcf220a27..ad8a8f2b6 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp @@ -80,12 +80,21 @@ void FuzzerPassPushIdsThroughVariables::Apply() { std::vector value_instructions = FindAvailableInstructions( function, block, instruction_iterator, - [basic_type_id](opt::IRContext* /*unused*/, - opt::Instruction* instruction) -> bool { + [basic_type_id, instruction_descriptor]( + opt::IRContext* ir_context, + opt::Instruction* instruction) -> bool { if (!instruction->result_id() || !instruction->type_id()) { return false; } - return instruction->type_id() == basic_type_id; + + if (instruction->type_id() != basic_type_id) { + return false; + } + + return fuzzerutil::IdIsAvailableBeforeInstruction( + ir_context, + FindInstruction(instruction_descriptor, ir_context), + instruction->result_id()); }); if (value_instructions.empty()) { diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_util.cpp b/3rdparty/spirv-tools/source/fuzz/fuzzer_util.cpp index f09943fe6..a5475d138 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_util.cpp +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_util.cpp @@ -550,6 +550,39 @@ bool IsNullConstantSupported(const opt::analysis::Type& type) { type.AsDeviceEvent() || type.AsReserveId() || type.AsQueue(); } +bool GlobalVariablesMustBeDeclaredInEntryPointInterfaces( + const opt::IRContext* ir_context) { + // TODO(afd): We capture the universal environments for which this requirement + // holds. The check should be refined on demand for other target + // environments. + switch (ir_context->grammar().target_env()) { + case SPV_ENV_UNIVERSAL_1_0: + case SPV_ENV_UNIVERSAL_1_1: + case SPV_ENV_UNIVERSAL_1_2: + case SPV_ENV_UNIVERSAL_1_3: + return false; + default: + return true; + } +} + +void AddVariableIdToEntryPointInterfaces(opt::IRContext* context, uint32_t id) { + if (GlobalVariablesMustBeDeclaredInEntryPointInterfaces(context)) { + // Conservatively add this global to the interface of every entry point in + // the module. This means that the global is available for other + // transformations to use. + // + // A downside of this is that the global will be in the interface even if it + // ends up never being used. + // + // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3111) revisit + // this if a more thorough approach to entry point interfaces is taken. + for (auto& entry_point : context->module()->entry_points()) { + entry_point.AddOperand({SPV_OPERAND_TYPE_ID, {id}}); + } + } +} + } // namespace fuzzerutil } // namespace fuzz diff --git a/3rdparty/spirv-tools/source/fuzz/fuzzer_util.h b/3rdparty/spirv-tools/source/fuzz/fuzzer_util.h index bccd1d015..fb2686b33 100644 --- a/3rdparty/spirv-tools/source/fuzz/fuzzer_util.h +++ b/3rdparty/spirv-tools/source/fuzz/fuzzer_util.h @@ -215,6 +215,17 @@ uint32_t MaybeGetPointerType(opt::IRContext* context, uint32_t pointee_type_id, // to have an OpConstantNull value. bool IsNullConstantSupported(const opt::analysis::Type& type); +// Returns true if and only if the SPIR-V version being used requires that +// global variables accessed in the static call graph of an entry point need +// to be listed in that entry point's interface. +bool GlobalVariablesMustBeDeclaredInEntryPointInterfaces( + const opt::IRContext* context); + +// Adds |id| into the interface of every entry point of the shader. +// Does nothing if SPIR-V doesn't require global variables, that are accessed +// from an entry point function, to be listed in that function's interface. +void AddVariableIdToEntryPointInterfaces(opt::IRContext* context, uint32_t id); + } // namespace fuzzerutil } // namespace fuzz diff --git a/3rdparty/spirv-tools/source/fuzz/protobufs/spvtoolsfuzz.proto b/3rdparty/spirv-tools/source/fuzz/protobufs/spvtoolsfuzz.proto index 645b73392..052af162a 100644 --- a/3rdparty/spirv-tools/source/fuzz/protobufs/spvtoolsfuzz.proto +++ b/3rdparty/spirv-tools/source/fuzz/protobufs/spvtoolsfuzz.proto @@ -376,6 +376,7 @@ message Transformation { TransformationComputeDataSynonymFactClosure compute_data_synonym_fact_closure = 45; TransformationAdjustBranchWeights adjust_branch_weights = 46; TransformationPushIdThroughVariable push_id_through_variable = 47; + TransformationAddSpecConstantOp add_spec_constant_op = 48; // Add additional option using the next available number. } } @@ -619,6 +620,24 @@ message TransformationAddNoContractionDecoration { } +message TransformationAddSpecConstantOp { + + // Adds OpSpecConstantOp into the module. + + // Result id for the new instruction. + uint32 fresh_id = 1; + + // Type id for the new instruction. + uint32 type_id = 2; + + // Opcode operand of the OpSpecConstantOp instruction. + uint32 opcode = 3; + + // Operands of the |opcode| instruction. + repeated InstructionOperand operand = 4; + +} + message TransformationAddTypeArray { // Adds an array type of the given element type and size to the module diff --git a/3rdparty/spirv-tools/source/fuzz/transformation.cpp b/3rdparty/spirv-tools/source/fuzz/transformation.cpp index 42168cb86..71e234890 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation.cpp +++ b/3rdparty/spirv-tools/source/fuzz/transformation.cpp @@ -30,6 +30,7 @@ #include "source/fuzz/transformation_add_global_variable.h" #include "source/fuzz/transformation_add_local_variable.h" #include "source/fuzz/transformation_add_no_contraction_decoration.h" +#include "source/fuzz/transformation_add_spec_constant_op.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" @@ -110,6 +111,9 @@ std::unique_ptr Transformation::FromMessage( kAddNoContractionDecoration: return MakeUnique( message.add_no_contraction_decoration()); + case protobufs::Transformation::TransformationCase::kAddSpecConstantOp: + return MakeUnique( + message.add_spec_constant_op()); case protobufs::Transformation::TransformationCase::kAddTypeArray: return MakeUnique(message.add_type_array()); case protobufs::Transformation::TransformationCase::kAddTypeBoolean: diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.cpp index 6464bfbb9..077ed6b27 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.cpp +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.cpp @@ -105,20 +105,8 @@ void TransformationAddGlobalVariable::Apply( input_operands)); fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id()); - if (GlobalVariablesMustBeDeclaredInEntryPointInterfaces(ir_context)) { - // Conservatively add this global to the interface of every entry point in - // the module. This means that the global is available for other - // transformations to use. - // - // A downside of this is that the global will be in the interface even if it - // ends up never being used. - // - // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3111) revisit - // this if a more thorough approach to entry point interfaces is taken. - for (auto& entry_point : ir_context->module()->entry_points()) { - entry_point.AddOperand({SPV_OPERAND_TYPE_ID, {message_.fresh_id()}}); - } - } + fuzzerutil::AddVariableIdToEntryPointInterfaces(ir_context, + message_.fresh_id()); if (message_.value_is_irrelevant()) { transformation_context->GetFactManager()->AddFactValueOfPointeeIsIrrelevant( @@ -137,22 +125,5 @@ protobufs::Transformation TransformationAddGlobalVariable::ToMessage() const { return result; } -bool TransformationAddGlobalVariable:: - GlobalVariablesMustBeDeclaredInEntryPointInterfaces( - opt::IRContext* ir_context) { - // TODO(afd): We capture the universal environments for which this requirement - // holds. The check should be refined on demand for other target - // environments. - switch (ir_context->grammar().target_env()) { - case SPV_ENV_UNIVERSAL_1_0: - case SPV_ENV_UNIVERSAL_1_1: - case SPV_ENV_UNIVERSAL_1_2: - case SPV_ENV_UNIVERSAL_1_3: - return false; - default: - return true; - } -} - } // namespace fuzz } // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.h b/3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.h index 289af9e9b..89bd044fd 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.h +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_global_variable.h @@ -58,12 +58,6 @@ class TransformationAddGlobalVariable : public Transformation { protobufs::Transformation ToMessage() const override; private: - // Returns true if and only if the SPIR-V version being used requires that - // global variables accessed in the static call graph of an entry point need - // to be listed in that entry point's interface. - static bool GlobalVariablesMustBeDeclaredInEntryPointInterfaces( - opt::IRContext* ir_context); - protobufs::TransformationAddGlobalVariable message_; }; diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_spec_constant_op.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_add_spec_constant_op.cpp new file mode 100644 index 000000000..d6a7083f5 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_spec_constant_op.cpp @@ -0,0 +1,84 @@ +// Copyright (c) 2020 Vasyl Teliman +// +// 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 + +#include "source/fuzz/fuzzer_util.h" +#include "source/fuzz/transformation_add_spec_constant_op.h" + +namespace spvtools { +namespace fuzz { + +TransformationAddSpecConstantOp::TransformationAddSpecConstantOp( + spvtools::fuzz::protobufs::TransformationAddSpecConstantOp message) + : message_(std::move(message)) {} + +TransformationAddSpecConstantOp::TransformationAddSpecConstantOp( + uint32_t fresh_id, uint32_t type_id, SpvOp opcode, + const opt::Instruction::OperandList& operands) { + message_.set_fresh_id(fresh_id); + message_.set_type_id(type_id); + message_.set_opcode(opcode); + for (const auto& operand : operands) { + auto* op = message_.add_operand(); + op->set_operand_type(operand.type); + for (auto word : operand.words) { + op->add_operand_data(word); + } + } +} + +bool TransformationAddSpecConstantOp::IsApplicable( + opt::IRContext* ir_context, + const TransformationContext& transformation_context) const { + auto clone = fuzzerutil::CloneIRContext(ir_context); + ApplyImpl(clone.get()); + return fuzzerutil::IsValid(clone.get(), + transformation_context.GetValidatorOptions()); +} + +void TransformationAddSpecConstantOp::Apply( + opt::IRContext* ir_context, TransformationContext* /*unused*/) const { + ApplyImpl(ir_context); + ir_context->InvalidateAnalysesExceptFor( + opt::IRContext::Analysis::kAnalysisNone); +} + +void TransformationAddSpecConstantOp::ApplyImpl( + opt::IRContext* ir_context) const { + opt::Instruction::OperandList operands = { + {SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER, {message_.opcode()}}}; + + for (const auto& operand : message_.operand()) { + std::vector words(operand.operand_data().begin(), + operand.operand_data().end()); + operands.push_back({static_cast(operand.operand_type()), + std::move(words)}); + } + + ir_context->AddGlobalValue(MakeUnique( + ir_context, SpvOpSpecConstantOp, message_.type_id(), message_.fresh_id(), + std::move(operands))); + + fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id()); +} + +protobufs::Transformation TransformationAddSpecConstantOp::ToMessage() const { + protobufs::Transformation result; + *result.mutable_add_spec_constant_op() = message_; + return result; +} + +} // namespace fuzz +} // namespace spvtools diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_add_spec_constant_op.h b/3rdparty/spirv-tools/source/fuzz/transformation_add_spec_constant_op.h new file mode 100644 index 000000000..c0f7154c9 --- /dev/null +++ b/3rdparty/spirv-tools/source/fuzz/transformation_add_spec_constant_op.h @@ -0,0 +1,60 @@ +// Copyright (c) 2020 Vasyl Teliman +// +// 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_SPEC_CONSTANT_OP_H_ +#define SOURCE_FUZZ_TRANSFORMATION_ADD_SPEC_CONSTANT_OP_H_ + +#include "source/fuzz/protobufs/spirvfuzz_protobufs.h" +#include "source/fuzz/transformation.h" +#include "source/fuzz/transformation_context.h" +#include "source/opt/ir_context.h" + +namespace spvtools { +namespace fuzz { + +class TransformationAddSpecConstantOp : public Transformation { + public: + explicit TransformationAddSpecConstantOp( + protobufs::TransformationAddSpecConstantOp message); + + TransformationAddSpecConstantOp( + uint32_t fresh_id, uint32_t type_id, SpvOp opcode, + const opt::Instruction::OperandList& operands); + + // - |fresh_id| is a fresh result id in the module. + // - |type_id| is a valid result id of some OpType* instruction in the + // module. It is also a valid type id with respect to |opcode|. + // - |opcode| is one of the opcodes supported by OpSpecConstantOp. + // - |operands| are valid with respect to |opcode| + bool IsApplicable( + opt::IRContext* ir_context, + const TransformationContext& transformation_context) const override; + + // |%fresh_id = OpSpecConstantOp %type_id opcode operands...| is added to the + // module. + void Apply(opt::IRContext* ir_context, + TransformationContext* transformation_context) const override; + + protobufs::Transformation ToMessage() const override; + + private: + void ApplyImpl(opt::IRContext* ir_context) const; + + protobufs::TransformationAddSpecConstantOp message_; +}; + +} // namespace fuzz +} // namespace spvtools + +#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_SPEC_CONSTANT_OP_H_ diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_push_id_through_variable.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_push_id_through_variable.cpp index c69114839..fb7946a7d 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation_push_id_through_variable.cpp +++ b/3rdparty/spirv-tools/source/fuzz/transformation_push_id_through_variable.cpp @@ -109,6 +109,9 @@ void TransformationPushIdThroughVariable::Apply( ir_context, SpvOpVariable, pointer_type_id, message_.variable_id(), opt::Instruction::OperandList( {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassPrivate}}}))); + + fuzzerutil::AddVariableIdToEntryPointInterfaces(ir_context, + message_.variable_id()); } else { ir_context ->get_instr_block( diff --git a/3rdparty/spirv-tools/source/fuzz/transformation_set_memory_operands_mask.cpp b/3rdparty/spirv-tools/source/fuzz/transformation_set_memory_operands_mask.cpp index 131a49942..f52f17014 100644 --- a/3rdparty/spirv-tools/source/fuzz/transformation_set_memory_operands_mask.cpp +++ b/3rdparty/spirv-tools/source/fuzz/transformation_set_memory_operands_mask.cpp @@ -101,6 +101,14 @@ void TransformationSetMemoryOperandsMask::Apply( // Either add a new operand, if no mask operand was already present, or // replace an existing mask operand. if (original_mask_in_operand_index >= instruction->NumInOperands()) { + // Add first memory operand if it's missing. + if (message_.memory_operands_mask_index() == 1 && + GetInOperandIndexForMask(*instruction, 0) >= + instruction->NumInOperands()) { + instruction->AddOperand( + {SPV_OPERAND_TYPE_MEMORY_ACCESS, {SpvMemoryAccessMaskNone}}); + } + instruction->AddOperand( {SPV_OPERAND_TYPE_MEMORY_ACCESS, {message_.memory_operands_mask()}}); @@ -154,11 +162,26 @@ uint32_t TransformationSetMemoryOperandsMask::GetInOperandIndexForMask( break; } // If we are looking for the input operand index of the first mask, return it. + // This will also return a correct value if the operand is missing. if (mask_index == 0) { return first_mask_in_operand_index; } assert(mask_index == 1 && "Memory operands mask index must be 0 or 1."); + // Memory mask operands are optional. Thus, if the second operand exists, + // its index will be >= |first_mask_in_operand_index + 1|. We can reason as + // follows to separate the cases where the index of the second operand is + // equal to |first_mask_in_operand_index + 1|: + // - If the first memory operand doesn't exist, its value is equal to None. + // This means that it doesn't have additional operands following it and the + // condition in the if statement below will be satisfied. + // - If the first memory operand exists and has no additional memory operands + // following it, the condition in the if statement below will be satisfied + // and we will return the correct value from the function. + if (first_mask_in_operand_index + 1 >= instruction.NumInOperands()) { + return first_mask_in_operand_index + 1; + } + // We are looking for the input operand index of the second mask. This is a // little complicated because, depending on the contents of the first mask, // there may be some input operands separating the two masks.