mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-02-18 04:53:06 +01:00
Updated spirv-tools.
This commit is contained in:
@@ -1 +1 @@
|
||||
"v2020.4-dev", "SPIRV-Tools v2020.4-dev 3e4a8382b6d054cbd8f0a04a4f83c4350dd803ea"
|
||||
"v2020.4-dev", "SPIRV-Tools v2020.4-dev 2cdcab3215d654e18c3b6d5f12bd94e7e64fb8b1"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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<uint32_t>(SpvMemoryAccessMaskNone);
|
||||
|
||||
|
||||
@@ -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<SpvOp>(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 "
|
||||
|
||||
@@ -80,12 +80,21 @@ void FuzzerPassPushIdsThroughVariables::Apply() {
|
||||
std::vector<opt::Instruction*> 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()) {
|
||||
|
||||
33
3rdparty/spirv-tools/source/fuzz/fuzzer_util.cpp
vendored
33
3rdparty/spirv-tools/source/fuzz/fuzzer_util.cpp
vendored
@@ -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
|
||||
|
||||
11
3rdparty/spirv-tools/source/fuzz/fuzzer_util.h
vendored
11
3rdparty/spirv-tools/source/fuzz/fuzzer_util.h
vendored
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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> Transformation::FromMessage(
|
||||
kAddNoContractionDecoration:
|
||||
return MakeUnique<TransformationAddNoContractionDecoration>(
|
||||
message.add_no_contraction_decoration());
|
||||
case protobufs::Transformation::TransformationCase::kAddSpecConstantOp:
|
||||
return MakeUnique<TransformationAddSpecConstantOp>(
|
||||
message.add_spec_constant_op());
|
||||
case protobufs::Transformation::TransformationCase::kAddTypeArray:
|
||||
return MakeUnique<TransformationAddTypeArray>(message.add_type_array());
|
||||
case protobufs::Transformation::TransformationCase::kAddTypeBoolean:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
|
||||
84
3rdparty/spirv-tools/source/fuzz/transformation_add_spec_constant_op.cpp
vendored
Normal file
84
3rdparty/spirv-tools/source/fuzz/transformation_add_spec_constant_op.cpp
vendored
Normal file
@@ -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 <utility>
|
||||
|
||||
#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<uint32_t> words(operand.operand_data().begin(),
|
||||
operand.operand_data().end());
|
||||
operands.push_back({static_cast<spv_operand_type_t>(operand.operand_type()),
|
||||
std::move(words)});
|
||||
}
|
||||
|
||||
ir_context->AddGlobalValue(MakeUnique<opt::Instruction>(
|
||||
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
|
||||
60
3rdparty/spirv-tools/source/fuzz/transformation_add_spec_constant_op.h
vendored
Normal file
60
3rdparty/spirv-tools/source/fuzz/transformation_add_spec_constant_op.h
vendored
Normal file
@@ -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_
|
||||
@@ -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(
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user