summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/3rdparty/spirv-tools/source/fuzz/instruction_descriptor.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/bgfx/3rdparty/spirv-tools/source/fuzz/instruction_descriptor.cpp')
-rw-r--r--3rdparty/bgfx/3rdparty/spirv-tools/source/fuzz/instruction_descriptor.cpp105
1 files changed, 105 insertions, 0 deletions
diff --git a/3rdparty/bgfx/3rdparty/spirv-tools/source/fuzz/instruction_descriptor.cpp b/3rdparty/bgfx/3rdparty/spirv-tools/source/fuzz/instruction_descriptor.cpp
new file mode 100644
index 00000000000..2b4217ab88d
--- /dev/null
+++ b/3rdparty/bgfx/3rdparty/spirv-tools/source/fuzz/instruction_descriptor.cpp
@@ -0,0 +1,105 @@
+// 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/instruction_descriptor.h"
+
+namespace spvtools {
+namespace fuzz {
+
+opt::Instruction* FindInstruction(
+ const protobufs::InstructionDescriptor& instruction_descriptor,
+ spvtools::opt::IRContext* context) {
+ for (auto& function : *context->module()) {
+ for (auto& block : function) {
+ bool found_base =
+ block.id() == instruction_descriptor.base_instruction_result_id();
+ uint32_t num_ignored = 0;
+ for (auto& instruction : block) {
+ if (instruction.HasResultId() &&
+ instruction.result_id() ==
+ instruction_descriptor.base_instruction_result_id()) {
+ assert(!found_base &&
+ "It should not be possible to find the base instruction "
+ "multiple times.");
+ found_base = true;
+ assert(num_ignored == 0 &&
+ "The skipped instruction count should only be incremented "
+ "after the instruction base has been found.");
+ }
+ if (found_base &&
+ instruction.opcode() ==
+ instruction_descriptor.target_instruction_opcode()) {
+ if (num_ignored == instruction_descriptor.num_opcodes_to_ignore()) {
+ return &instruction;
+ }
+ num_ignored++;
+ }
+ }
+ if (found_base) {
+ // We found the base instruction, but did not find the target
+ // instruction in the same block.
+ return nullptr;
+ }
+ }
+ }
+ return nullptr;
+}
+
+protobufs::InstructionDescriptor MakeInstructionDescriptor(
+ uint32_t base_instruction_result_id, SpvOp target_instruction_opcode,
+ uint32_t num_opcodes_to_ignore) {
+ protobufs::InstructionDescriptor result;
+ result.set_base_instruction_result_id(base_instruction_result_id);
+ result.set_target_instruction_opcode(target_instruction_opcode);
+ result.set_num_opcodes_to_ignore(num_opcodes_to_ignore);
+ return result;
+}
+
+protobufs::InstructionDescriptor MakeInstructionDescriptor(
+ const opt::BasicBlock& block,
+ const opt::BasicBlock::const_iterator& inst_it) {
+ const SpvOp opcode =
+ inst_it->opcode(); // The opcode of the instruction being described.
+ uint32_t skip_count = 0; // The number of these opcodes we have skipped when
+ // searching backwards.
+
+ // Consider instructions in the block in reverse order, starting from
+ // |inst_it|.
+ for (opt::BasicBlock::const_iterator backwards_iterator = inst_it;;
+ --backwards_iterator) {
+ if (backwards_iterator->HasResultId()) {
+ // As soon as we find an instruction with a result id, we can return a
+ // descriptor for |inst_it|.
+ return MakeInstructionDescriptor(backwards_iterator->result_id(), opcode,
+ skip_count);
+ }
+ if (backwards_iterator != inst_it &&
+ backwards_iterator->opcode() == opcode) {
+ // We are skipping over an instruction with the same opcode as |inst_it|;
+ // we increase our skip count to reflect this.
+ skip_count++;
+ }
+ if (backwards_iterator == block.begin()) {
+ // We exit the loop when we reach the start of the block, but only after
+ // we have processed the first instruction in the block.
+ break;
+ }
+ }
+ // We did not find an instruction inside the block with a result id, so we use
+ // the block's label's id.
+ return MakeInstructionDescriptor(block.id(), opcode, skip_count);
+}
+
+} // namespace fuzz
+} // namespace spvtools