// 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.h"

#include <set>

#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/id_use_descriptor.h"
#include "source/fuzz/instruction_descriptor.h"
#include "source/fuzz/transformation_add_constant_boolean.h"
#include "source/fuzz/transformation_add_constant_composite.h"
#include "source/fuzz/transformation_add_constant_null.h"
#include "source/fuzz/transformation_add_constant_scalar.h"
#include "source/fuzz/transformation_add_global_undef.h"
#include "source/fuzz/transformation_add_global_variable.h"
#include "source/fuzz/transformation_add_local_variable.h"
#include "source/fuzz/transformation_add_loop_preheader.h"
#include "source/fuzz/transformation_add_type_boolean.h"
#include "source/fuzz/transformation_add_type_float.h"
#include "source/fuzz/transformation_add_type_function.h"
#include "source/fuzz/transformation_add_type_int.h"
#include "source/fuzz/transformation_add_type_matrix.h"
#include "source/fuzz/transformation_add_type_pointer.h"
#include "source/fuzz/transformation_add_type_struct.h"
#include "source/fuzz/transformation_add_type_vector.h"
#include "source/fuzz/transformation_split_block.h"

namespace spvtools {
namespace fuzz {

FuzzerPass::FuzzerPass(opt::IRContext* ir_context,
                       TransformationContext* transformation_context,
                       FuzzerContext* fuzzer_context,
                       protobufs::TransformationSequence* transformations,
                       bool ignore_inapplicable_transformations)
    : ir_context_(ir_context),
      transformation_context_(transformation_context),
      fuzzer_context_(fuzzer_context),
      transformations_(transformations),
      ignore_inapplicable_transformations_(
          ignore_inapplicable_transformations) {}

FuzzerPass::~FuzzerPass() = default;

std::vector<opt::Instruction*> FuzzerPass::FindAvailableInstructions(
    opt::Function* function, opt::BasicBlock* block,
    const opt::BasicBlock::iterator& inst_it,
    std::function<bool(opt::IRContext*, opt::Instruction*)>
        instruction_is_relevant) const {
  // TODO(afd) The following is (relatively) simple, but may end up being
  //  prohibitively inefficient, as it walks the whole dominator tree for
  //  every instruction that is considered.

  std::vector<opt::Instruction*> result;
  // Consider all global declarations
  for (auto& global : GetIRContext()->module()->types_values()) {
    if (instruction_is_relevant(GetIRContext(), &global)) {
      result.push_back(&global);
    }
  }

  // Consider all function parameters
  function->ForEachParam(
      [this, &instruction_is_relevant, &result](opt::Instruction* param) {
        if (instruction_is_relevant(GetIRContext(), param)) {
          result.push_back(param);
        }
      });

  // Consider all previous instructions in this block
  for (auto prev_inst_it = block->begin(); prev_inst_it != inst_it;
       ++prev_inst_it) {
    if (instruction_is_relevant(GetIRContext(), &*prev_inst_it)) {
      result.push_back(&*prev_inst_it);
    }
  }

  // Walk the dominator tree to consider all instructions from dominating
  // blocks
  auto dominator_analysis = GetIRContext()->GetDominatorAnalysis(function);
  for (auto next_dominator = dominator_analysis->ImmediateDominator(block);
       next_dominator != nullptr;
       next_dominator =
           dominator_analysis->ImmediateDominator(next_dominator)) {
    for (auto& dominating_inst : *next_dominator) {
      if (instruction_is_relevant(GetIRContext(), &dominating_inst)) {
        result.push_back(&dominating_inst);
      }
    }
  }
  return result;
}

void FuzzerPass::ForEachInstructionWithInstructionDescriptor(
    opt::Function* function,
    std::function<
        void(opt::BasicBlock* block, opt::BasicBlock::iterator inst_it,
             const protobufs::InstructionDescriptor& instruction_descriptor)>
        action) {
  // Consider only reachable blocks. We do this in a separate loop to avoid
  // recomputing the dominator analysis every time |action| changes the
  // module.
  std::vector<opt::BasicBlock*> reachable_blocks;

  for (auto& block : *function) {
    if (GetIRContext()->IsReachable(block)) {
      reachable_blocks.push_back(&block);
    }
  }

  for (auto* block : reachable_blocks) {
    // We now consider every instruction in the block, randomly deciding
    // whether to apply a transformation before it.

    // In order for transformations to insert new instructions, they need to
    // be able to identify the instruction to insert before.  We describe an
    // instruction via its opcode, 'opc', a base instruction 'base' that has a
    // result id, and the number of instructions with opcode 'opc' that we
    // should skip when searching from 'base' for the desired instruction.
    // (An instruction that has a result id is represented by its own opcode,
    // itself as 'base', and a skip-count of 0.)
    std::vector<std::tuple<uint32_t, SpvOp, uint32_t>> base_opcode_skip_triples;

    // The initial base instruction is the block label.
    uint32_t base = block->id();

    // Counts the number of times we have seen each opcode since we reset the
    // base instruction.
    std::map<SpvOp, uint32_t> skip_count;

    // Consider every instruction in the block.  The label is excluded: it is
    // only necessary to consider it as a base in case the first instruction
    // in the block does not have a result id.
    for (auto inst_it = block->begin(); inst_it != block->end(); ++inst_it) {
      if (inst_it->HasResultId()) {
        // In the case that the instruction has a result id, we use the
        // instruction as its own base, and clear the skip counts we have
        // collected.
        base = inst_it->result_id();
        skip_count.clear();
      }
      const SpvOp opcode = inst_it->opcode();

      // Invoke the provided function, which might apply a transformation.
      action(block, inst_it,
             MakeInstructionDescriptor(
                 base, opcode,
                 skip_count.count(opcode) ? skip_count.at(opcode) : 0));

      if (!inst_it->HasResultId()) {
        skip_count[opcode] =
            skip_count.count(opcode) ? skip_count.at(opcode) + 1 : 1;
      }
    }
  }
}

void FuzzerPass::ForEachInstructionWithInstructionDescriptor(
    std::function<
        void(opt::Function* function, opt::BasicBlock* block,
             opt::BasicBlock::iterator inst_it,
             const protobufs::InstructionDescriptor& instruction_descriptor)>
        action) {
  // Consider every block in every function.
  for (auto& function : *GetIRContext()->module()) {
    ForEachInstructionWithInstructionDescriptor(
        &function,
        [&action, &function](
            opt::BasicBlock* block, opt::BasicBlock::iterator inst_it,
            const protobufs::InstructionDescriptor& instruction_descriptor) {
          action(&function, block, inst_it, instruction_descriptor);
        });
  }
}

void FuzzerPass::ApplyTransformation(const Transformation& transformation) {
  if (ignore_inapplicable_transformations_) {
    // If an applicable-by-construction transformation turns out to be
    // inapplicable, this is a bug in the fuzzer. However, when deploying the
    // fuzzer at scale for finding bugs in SPIR-V processing tools it is
    // desirable to silently ignore such bugs. This code path caters for that
    // scenario.
    if (!transformation.IsApplicable(GetIRContext(),
                                     *GetTransformationContext())) {
      return;
    }
  } else {
    // This code path caters for debugging bugs in the fuzzer, where an
    // applicable-by-construction transformation turns out to be inapplicable.
    assert(transformation.IsApplicable(GetIRContext(),
                                       *GetTransformationContext()) &&
           "Transformation should be applicable by construction.");
  }
  transformation.Apply(GetIRContext(), GetTransformationContext());
  auto transformation_message = transformation.ToMessage();
  assert(transformation_message.transformation_case() !=
             protobufs::Transformation::TRANSFORMATION_NOT_SET &&
         "Bad transformation.");
  *GetTransformations()->add_transformation() =
      std::move(transformation_message);
}

bool FuzzerPass::MaybeApplyTransformation(
    const Transformation& transformation) {
  if (transformation.IsApplicable(GetIRContext(),
                                  *GetTransformationContext())) {
    transformation.Apply(GetIRContext(), GetTransformationContext());
    auto transformation_message = transformation.ToMessage();
    assert(transformation_message.transformation_case() !=
               protobufs::Transformation::TRANSFORMATION_NOT_SET &&
           "Bad transformation.");
    *GetTransformations()->add_transformation() =
        std::move(transformation_message);
    return true;
  }
  return false;
}

uint32_t FuzzerPass::FindOrCreateBoolType() {
  if (auto existing_id = fuzzerutil::MaybeGetBoolType(GetIRContext())) {
    return existing_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddTypeBoolean(result));
  return result;
}

uint32_t FuzzerPass::FindOrCreateIntegerType(uint32_t width, bool is_signed) {
  opt::analysis::Integer int_type(width, is_signed);
  auto existing_id = GetIRContext()->get_type_mgr()->GetId(&int_type);
  if (existing_id) {
    return existing_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddTypeInt(result, width, is_signed));
  return result;
}

uint32_t FuzzerPass::FindOrCreateFloatType(uint32_t width) {
  opt::analysis::Float float_type(width);
  auto existing_id = GetIRContext()->get_type_mgr()->GetId(&float_type);
  if (existing_id) {
    return existing_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddTypeFloat(result, width));
  return result;
}

uint32_t FuzzerPass::FindOrCreateFunctionType(
    uint32_t return_type_id, const std::vector<uint32_t>& argument_id) {
  // FindFunctionType has a sigle argument for OpTypeFunction operands
  // so we will have to copy them all in this vector
  std::vector<uint32_t> type_ids(argument_id.size() + 1);
  type_ids[0] = return_type_id;
  std::copy(argument_id.begin(), argument_id.end(), type_ids.begin() + 1);

  // Check if type exists
  auto existing_id = fuzzerutil::FindFunctionType(GetIRContext(), type_ids);
  if (existing_id) {
    return existing_id;
  }

  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(
      TransformationAddTypeFunction(result, return_type_id, argument_id));
  return result;
}

uint32_t FuzzerPass::FindOrCreateVectorType(uint32_t component_type_id,
                                            uint32_t component_count) {
  assert(component_count >= 2 && component_count <= 4 &&
         "Precondition: component count must be in range [2, 4].");
  opt::analysis::Type* component_type =
      GetIRContext()->get_type_mgr()->GetType(component_type_id);
  assert(component_type && "Precondition: the component type must exist.");
  opt::analysis::Vector vector_type(component_type, component_count);
  auto existing_id = GetIRContext()->get_type_mgr()->GetId(&vector_type);
  if (existing_id) {
    return existing_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(
      TransformationAddTypeVector(result, component_type_id, component_count));
  return result;
}

uint32_t FuzzerPass::FindOrCreateMatrixType(uint32_t column_count,
                                            uint32_t row_count) {
  assert(column_count >= 2 && column_count <= 4 &&
         "Precondition: column count must be in range [2, 4].");
  assert(row_count >= 2 && row_count <= 4 &&
         "Precondition: row count must be in range [2, 4].");
  uint32_t column_type_id =
      FindOrCreateVectorType(FindOrCreateFloatType(32), row_count);
  opt::analysis::Type* column_type =
      GetIRContext()->get_type_mgr()->GetType(column_type_id);
  opt::analysis::Matrix matrix_type(column_type, column_count);
  auto existing_id = GetIRContext()->get_type_mgr()->GetId(&matrix_type);
  if (existing_id) {
    return existing_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(
      TransformationAddTypeMatrix(result, column_type_id, column_count));
  return result;
}

uint32_t FuzzerPass::FindOrCreateStructType(
    const std::vector<uint32_t>& component_type_ids) {
  if (auto existing_id =
          fuzzerutil::MaybeGetStructType(GetIRContext(), component_type_ids)) {
    return existing_id;
  }
  auto new_id = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddTypeStruct(new_id, component_type_ids));
  return new_id;
}

uint32_t FuzzerPass::FindOrCreatePointerType(uint32_t base_type_id,
                                             SpvStorageClass storage_class) {
  // We do not use the type manager here, due to problems related to isomorphic
  // but distinct structs not being regarded as different.
  auto existing_id = fuzzerutil::MaybeGetPointerType(
      GetIRContext(), base_type_id, storage_class);
  if (existing_id) {
    return existing_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(
      TransformationAddTypePointer(result, storage_class, base_type_id));
  return result;
}

uint32_t FuzzerPass::FindOrCreatePointerToIntegerType(
    uint32_t width, bool is_signed, SpvStorageClass storage_class) {
  return FindOrCreatePointerType(FindOrCreateIntegerType(width, is_signed),
                                 storage_class);
}

uint32_t FuzzerPass::FindOrCreateIntegerConstant(
    const std::vector<uint32_t>& words, uint32_t width, bool is_signed,
    bool is_irrelevant) {
  auto int_type_id = FindOrCreateIntegerType(width, is_signed);
  if (auto constant_id = fuzzerutil::MaybeGetScalarConstant(
          GetIRContext(), *GetTransformationContext(), words, int_type_id,
          is_irrelevant)) {
    return constant_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddConstantScalar(result, int_type_id,
                                                      words, is_irrelevant));
  return result;
}

uint32_t FuzzerPass::FindOrCreateFloatConstant(
    const std::vector<uint32_t>& words, uint32_t width, bool is_irrelevant) {
  auto float_type_id = FindOrCreateFloatType(width);
  if (auto constant_id = fuzzerutil::MaybeGetScalarConstant(
          GetIRContext(), *GetTransformationContext(), words, float_type_id,
          is_irrelevant)) {
    return constant_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddConstantScalar(result, float_type_id,
                                                      words, is_irrelevant));
  return result;
}

uint32_t FuzzerPass::FindOrCreateBoolConstant(bool value, bool is_irrelevant) {
  auto bool_type_id = FindOrCreateBoolType();
  if (auto constant_id = fuzzerutil::MaybeGetScalarConstant(
          GetIRContext(), *GetTransformationContext(), {value ? 1u : 0u},
          bool_type_id, is_irrelevant)) {
    return constant_id;
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(
      TransformationAddConstantBoolean(result, value, is_irrelevant));
  return result;
}

uint32_t FuzzerPass::FindOrCreateConstant(const std::vector<uint32_t>& words,
                                          uint32_t type_id,
                                          bool is_irrelevant) {
  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], is_irrelevant);
  } else if (const auto* integer = type->AsInteger()) {
    return FindOrCreateIntegerConstant(words, integer->width(),
                                       integer->IsSigned(), is_irrelevant);
  } else if (const auto* floating = type->AsFloat()) {
    return FindOrCreateFloatConstant(words, floating->width(), is_irrelevant);
  }

  // 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::FindOrCreateCompositeConstant(
    const std::vector<uint32_t>& component_ids, uint32_t type_id,
    bool is_irrelevant) {
  if (auto existing_constant = fuzzerutil::MaybeGetCompositeConstant(
          GetIRContext(), *GetTransformationContext(), component_ids, type_id,
          is_irrelevant)) {
    return existing_constant;
  }
  uint32_t result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddConstantComposite(
      result, type_id, component_ids, is_irrelevant));
  return result;
}

uint32_t FuzzerPass::FindOrCreateGlobalUndef(uint32_t type_id) {
  for (auto& inst : GetIRContext()->types_values()) {
    if (inst.opcode() == SpvOpUndef && inst.type_id() == type_id) {
      return inst.result_id();
    }
  }
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddGlobalUndef(result, type_id));
  return result;
}

uint32_t FuzzerPass::FindOrCreateNullConstant(uint32_t type_id) {
  // Find existing declaration
  opt::analysis::NullConstant null_constant(
      GetIRContext()->get_type_mgr()->GetType(type_id));
  auto existing_constant =
      GetIRContext()->get_constant_mgr()->FindConstant(&null_constant);

  // Return if found
  if (existing_constant) {
    return GetIRContext()
        ->get_constant_mgr()
        ->GetDefiningInstruction(existing_constant)
        ->result_id();
  }

  // Create new if not found
  auto result = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddConstantNull(result, type_id));
  return result;
}

std::pair<std::vector<uint32_t>, std::map<uint32_t, std::vector<uint32_t>>>
FuzzerPass::GetAvailableBasicTypesAndPointers(
    SpvStorageClass storage_class) const {
  // Records all of the basic types available in the module.
  std::set<uint32_t> basic_types;

  // For each basic type, records all the associated pointer types that target
  // the basic type and that have |storage_class| as their storage class.
  std::map<uint32_t, std::vector<uint32_t>> basic_type_to_pointers;

  for (auto& inst : GetIRContext()->types_values()) {
    // For each basic type that we come across, record type, and the fact that
    // we cannot yet have seen any pointers that use the basic type as its
    // pointee type.
    //
    // For pointer types with basic pointee types, associate the pointer type
    // with the basic type.
    switch (inst.opcode()) {
      case SpvOpTypeBool:
      case SpvOpTypeFloat:
      case SpvOpTypeInt:
      case SpvOpTypeMatrix:
      case SpvOpTypeVector:
        // These are all basic types.
        basic_types.insert(inst.result_id());
        basic_type_to_pointers.insert({inst.result_id(), {}});
        break;
      case SpvOpTypeArray:
        // An array type is basic if its base type is basic.
        if (basic_types.count(inst.GetSingleWordInOperand(0))) {
          basic_types.insert(inst.result_id());
          basic_type_to_pointers.insert({inst.result_id(), {}});
        }
        break;
      case SpvOpTypeStruct: {
        // A struct type is basic if it does not have the Block/BufferBlock
        // decoration, and if all of its members are basic.
        if (!fuzzerutil::HasBlockOrBufferBlockDecoration(GetIRContext(),
                                                         inst.result_id())) {
          bool all_members_are_basic_types = true;
          for (uint32_t i = 0; i < inst.NumInOperands(); i++) {
            if (!basic_types.count(inst.GetSingleWordInOperand(i))) {
              all_members_are_basic_types = false;
              break;
            }
          }
          if (all_members_are_basic_types) {
            basic_types.insert(inst.result_id());
            basic_type_to_pointers.insert({inst.result_id(), {}});
          }
        }
        break;
      }
      case SpvOpTypePointer: {
        // We are interested in the pointer if its pointee type is basic and it
        // has the right storage class.
        auto pointee_type = inst.GetSingleWordInOperand(1);
        if (inst.GetSingleWordInOperand(0) == storage_class &&
            basic_types.count(pointee_type)) {
          // The pointer has the desired storage class, and its pointee type is
          // a basic type, so we are interested in it.  Associate it with its
          // basic type.
          basic_type_to_pointers.at(pointee_type).push_back(inst.result_id());
        }
        break;
      }
      default:
        break;
    }
  }
  return {{basic_types.begin(), basic_types.end()}, basic_type_to_pointers};
}

uint32_t FuzzerPass::FindOrCreateZeroConstant(
    uint32_t scalar_or_composite_type_id, bool is_irrelevant) {
  auto type_instruction =
      GetIRContext()->get_def_use_mgr()->GetDef(scalar_or_composite_type_id);
  assert(type_instruction && "The type instruction must exist.");
  switch (type_instruction->opcode()) {
    case SpvOpTypeBool:
      return FindOrCreateBoolConstant(false, is_irrelevant);
    case SpvOpTypeFloat: {
      auto width = type_instruction->GetSingleWordInOperand(0);
      auto num_words = (width + 32 - 1) / 32;
      return FindOrCreateFloatConstant(std::vector<uint32_t>(num_words, 0),
                                       width, is_irrelevant);
    }
    case SpvOpTypeInt: {
      auto width = type_instruction->GetSingleWordInOperand(0);
      auto num_words = (width + 32 - 1) / 32;
      return FindOrCreateIntegerConstant(
          std::vector<uint32_t>(num_words, 0), width,
          type_instruction->GetSingleWordInOperand(1), is_irrelevant);
    }
    case SpvOpTypeArray: {
      auto component_type_id = type_instruction->GetSingleWordInOperand(0);
      auto num_components =
          fuzzerutil::GetArraySize(*type_instruction, GetIRContext());
      return FindOrCreateCompositeConstant(
          std::vector<uint32_t>(
              num_components,
              FindOrCreateZeroConstant(component_type_id, is_irrelevant)),
          scalar_or_composite_type_id, is_irrelevant);
    }
    case SpvOpTypeMatrix:
    case SpvOpTypeVector: {
      auto component_type_id = type_instruction->GetSingleWordInOperand(0);
      auto num_components = type_instruction->GetSingleWordInOperand(1);
      return FindOrCreateCompositeConstant(
          std::vector<uint32_t>(
              num_components,
              FindOrCreateZeroConstant(component_type_id, is_irrelevant)),
          scalar_or_composite_type_id, is_irrelevant);
    }
    case SpvOpTypeStruct: {
      assert(!fuzzerutil::HasBlockOrBufferBlockDecoration(
                 GetIRContext(), scalar_or_composite_type_id) &&
             "We do not construct constants of struct types decorated with "
             "Block or BufferBlock.");
      std::vector<uint32_t> field_zero_ids;
      for (uint32_t index = 0; index < type_instruction->NumInOperands();
           index++) {
        field_zero_ids.push_back(FindOrCreateZeroConstant(
            type_instruction->GetSingleWordInOperand(index), is_irrelevant));
      }
      return FindOrCreateCompositeConstant(
          field_zero_ids, scalar_or_composite_type_id, is_irrelevant);
    }
    default:
      assert(false && "Unknown type.");
      return 0;
  }
}

void FuzzerPass::MaybeAddUseToReplace(
    opt::Instruction* use_inst, uint32_t use_index, uint32_t replacement_id,
    std::vector<std::pair<protobufs::IdUseDescriptor, uint32_t>>*
        uses_to_replace) {
  // Only consider this use if it is in a block
  if (!GetIRContext()->get_instr_block(use_inst)) {
    return;
  }

  // Get the index of the operand restricted to input operands.
  uint32_t in_operand_index =
      fuzzerutil::InOperandIndexFromOperandIndex(*use_inst, use_index);
  auto id_use_descriptor =
      MakeIdUseDescriptorFromUse(GetIRContext(), use_inst, in_operand_index);
  uses_to_replace->emplace_back(
      std::make_pair(id_use_descriptor, replacement_id));
}

opt::BasicBlock* FuzzerPass::GetOrCreateSimpleLoopPreheader(
    uint32_t header_id) {
  auto header_block = fuzzerutil::MaybeFindBlock(GetIRContext(), header_id);

  assert(header_block && header_block->IsLoopHeader() &&
         "|header_id| should be the label id of a loop header");

  auto predecessors = GetIRContext()->cfg()->preds(header_id);

  assert(predecessors.size() >= 2 &&
         "The block |header_id| should be reachable.");

  auto function = header_block->GetParent();

  if (predecessors.size() == 2) {
    // The header has a single out-of-loop predecessor, which could be a
    // preheader.

    opt::BasicBlock* maybe_preheader;

    if (GetIRContext()->GetDominatorAnalysis(function)->Dominates(
            header_id, predecessors[0])) {
      // The first predecessor is the back-edge block, because the header
      // dominates it, so the second one is out of the loop.
      maybe_preheader = &*function->FindBlock(predecessors[1]);
    } else {
      // The first predecessor is out of the loop.
      maybe_preheader = &*function->FindBlock(predecessors[0]);
    }

    // |maybe_preheader| is a preheader if it branches unconditionally to
    // the header. We also require it not to be a loop header.
    if (maybe_preheader->terminator()->opcode() == SpvOpBranch &&
        !maybe_preheader->IsLoopHeader()) {
      return maybe_preheader;
    }
  }

  // We need to add a preheader.

  // Get a fresh id for the preheader.
  uint32_t preheader_id = GetFuzzerContext()->GetFreshId();

  // Get a fresh id for each OpPhi instruction, if there is more than one
  // out-of-loop predecessor.
  std::vector<uint32_t> phi_ids;
  if (predecessors.size() > 2) {
    header_block->ForEachPhiInst(
        [this, &phi_ids](opt::Instruction* /* unused */) {
          phi_ids.push_back(GetFuzzerContext()->GetFreshId());
        });
  }

  // Add the preheader.
  ApplyTransformation(
      TransformationAddLoopPreheader(header_id, preheader_id, phi_ids));

  // Make the newly-created preheader the new entry block.
  return &*function->FindBlock(preheader_id);
}

opt::BasicBlock* FuzzerPass::SplitBlockAfterOpPhiOrOpVariable(
    uint32_t block_id) {
  auto block = fuzzerutil::MaybeFindBlock(GetIRContext(), block_id);
  assert(block && "|block_id| must be a block label");
  assert(!block->IsLoopHeader() && "|block_id| cannot be a loop header");

  // Find the first non-OpPhi and non-OpVariable instruction.
  auto non_phi_or_var_inst = &*block->begin();
  while (non_phi_or_var_inst->opcode() == SpvOpPhi ||
         non_phi_or_var_inst->opcode() == SpvOpVariable) {
    non_phi_or_var_inst = non_phi_or_var_inst->NextNode();
  }

  // Split the block.
  uint32_t new_block_id = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationSplitBlock(
      MakeInstructionDescriptor(GetIRContext(), non_phi_or_var_inst),
      new_block_id));

  // We need to return the newly-created block.
  return &*block->GetParent()->FindBlock(new_block_id);
}

uint32_t FuzzerPass::FindOrCreateLocalVariable(
    uint32_t pointer_type_id, uint32_t function_id,
    bool pointee_value_is_irrelevant) {
  auto pointer_type = GetIRContext()->get_type_mgr()->GetType(pointer_type_id);
  // No unused variables in release mode.
  (void)pointer_type;
  assert(pointer_type && pointer_type->AsPointer() &&
         pointer_type->AsPointer()->storage_class() ==
             SpvStorageClassFunction &&
         "The pointer_type_id must refer to a defined pointer type with "
         "storage class Function");
  auto function = fuzzerutil::FindFunction(GetIRContext(), function_id);
  assert(function && "The function must be defined.");

  // First we try to find a suitable existing variable.
  // All of the local variable declarations are located in the first block.
  for (auto& instruction : *function->begin()) {
    if (instruction.opcode() != SpvOpVariable) {
      continue;
    }
    // The existing OpVariable must have type |pointer_type_id|.
    if (instruction.type_id() != pointer_type_id) {
      continue;
    }
    // Check if the found variable is marked with PointeeValueIsIrrelevant
    // according to |pointee_value_is_irrelevant|.
    if (GetTransformationContext()->GetFactManager()->PointeeValueIsIrrelevant(
            instruction.result_id()) != pointee_value_is_irrelevant) {
      continue;
    }
    return instruction.result_id();
  }

  // No such variable was found. Apply a transformation to get one.
  uint32_t pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType(
      GetIRContext(), pointer_type_id);
  uint32_t result_id = GetFuzzerContext()->GetFreshId();
  ApplyTransformation(TransformationAddLocalVariable(
      result_id, pointer_type_id, function_id,
      FindOrCreateZeroConstant(pointee_type_id, pointee_value_is_irrelevant),
      pointee_value_is_irrelevant));
  return result_id;
}

uint32_t FuzzerPass::FindOrCreateGlobalVariable(
    uint32_t pointer_type_id, bool pointee_value_is_irrelevant) {
  auto pointer_type = GetIRContext()->get_type_mgr()->GetType(pointer_type_id);
  // No unused variables in release mode.
  (void)pointer_type;
  assert(
      pointer_type && pointer_type->AsPointer() &&
      (pointer_type->AsPointer()->storage_class() == SpvStorageClassPrivate ||
       pointer_type->AsPointer()->storage_class() ==
           SpvStorageClassWorkgroup) &&
      "The pointer_type_id must refer to a defined pointer type with storage "
      "class Private or Workgroup");

  // First we try to find a suitable existing variable.
  for (auto& instruction : GetIRContext()->module()->types_values()) {
    if (instruction.opcode() != SpvOpVariable) {
      continue;
    }
    // The existing OpVariable must have type |pointer_type_id|.
    if (instruction.type_id() != pointer_type_id) {
      continue;
    }
    // Check if the found variable is marked with PointeeValueIsIrrelevant
    // according to |pointee_value_is_irrelevant|.
    if (GetTransformationContext()->GetFactManager()->PointeeValueIsIrrelevant(
            instruction.result_id()) != pointee_value_is_irrelevant) {
      continue;
    }
    return instruction.result_id();
  }

  // No such variable was found. Apply a transformation to get one.
  uint32_t pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType(
      GetIRContext(), pointer_type_id);
  auto storage_class = fuzzerutil::GetStorageClassFromPointerType(
      GetIRContext(), pointer_type_id);
  uint32_t result_id = GetFuzzerContext()->GetFreshId();

  // A variable with storage class Workgroup shouldn't have an initializer.
  if (storage_class == SpvStorageClassWorkgroup) {
    ApplyTransformation(TransformationAddGlobalVariable(
        result_id, pointer_type_id, SpvStorageClassWorkgroup, 0,
        pointee_value_is_irrelevant));
  } else {
    ApplyTransformation(TransformationAddGlobalVariable(
        result_id, pointer_type_id, SpvStorageClassPrivate,
        FindOrCreateZeroConstant(pointee_type_id, pointee_value_is_irrelevant),
        pointee_value_is_irrelevant));
  }
  return result_id;
}

}  // namespace fuzz
}  // namespace spvtools
