// Copyright (c) 2016 Google Inc.
//
// 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/opt/instruction.h"

#include <initializer_list>

#include "OpenCLDebugInfo100.h"
#include "source/disassemble.h"
#include "source/opt/fold.h"
#include "source/opt/ir_context.h"
#include "source/opt/reflect.h"

namespace spvtools {
namespace opt {
namespace {
// Indices used to get particular operands out of instructions using InOperand.
constexpr uint32_t kTypeImageDimIndex = 1;
constexpr uint32_t kLoadBaseIndex = 0;
constexpr uint32_t kPointerTypeStorageClassIndex = 0;
constexpr uint32_t kVariableStorageClassIndex = 0;
constexpr uint32_t kTypeImageSampledIndex = 5;

// Constants for OpenCL.DebugInfo.100 / NonSemantic.Shader.DebugInfo.100
// extension instructions.
constexpr uint32_t kExtInstSetIdInIdx = 0;
constexpr uint32_t kExtInstInstructionInIdx = 1;
constexpr uint32_t kDebugScopeNumWords = 7;
constexpr uint32_t kDebugScopeNumWordsWithoutInlinedAt = 6;
constexpr uint32_t kDebugNoScopeNumWords = 5;

// Number of operands of an OpBranchConditional instruction
// with weights.
constexpr uint32_t kOpBranchConditionalWithWeightsNumOperands = 5;
}  // namespace

Instruction::Instruction(IRContext* c)
    : utils::IntrusiveNodeBase<Instruction>(),
      context_(c),
      opcode_(spv::Op::OpNop),
      has_type_id_(false),
      has_result_id_(false),
      unique_id_(c->TakeNextUniqueId()),
      dbg_scope_(kNoDebugScope, kNoInlinedAt) {}

Instruction::Instruction(IRContext* c, spv::Op op)
    : utils::IntrusiveNodeBase<Instruction>(),
      context_(c),
      opcode_(op),
      has_type_id_(false),
      has_result_id_(false),
      unique_id_(c->TakeNextUniqueId()),
      dbg_scope_(kNoDebugScope, kNoInlinedAt) {}

Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
                         std::vector<Instruction>&& dbg_line)
    : utils::IntrusiveNodeBase<Instruction>(),
      context_(c),
      opcode_(static_cast<spv::Op>(inst.opcode)),
      has_type_id_(inst.type_id != 0),
      has_result_id_(inst.result_id != 0),
      unique_id_(c->TakeNextUniqueId()),
      dbg_line_insts_(std::move(dbg_line)),
      dbg_scope_(kNoDebugScope, kNoInlinedAt) {
  operands_.reserve(inst.num_operands);
  for (uint32_t i = 0; i < inst.num_operands; ++i) {
    const auto& current_payload = inst.operands[i];
    operands_.emplace_back(
        current_payload.type, inst.words + current_payload.offset,
        inst.words + current_payload.offset + current_payload.num_words);
  }
  assert((!IsLineInst() || dbg_line.empty()) &&
         "Op(No)Line attaching to Op(No)Line found");
}

Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
                         const DebugScope& dbg_scope)
    : utils::IntrusiveNodeBase<Instruction>(),
      context_(c),
      opcode_(static_cast<spv::Op>(inst.opcode)),
      has_type_id_(inst.type_id != 0),
      has_result_id_(inst.result_id != 0),
      unique_id_(c->TakeNextUniqueId()),
      dbg_scope_(dbg_scope) {
  operands_.reserve(inst.num_operands);
  for (uint32_t i = 0; i < inst.num_operands; ++i) {
    const auto& current_payload = inst.operands[i];
    operands_.emplace_back(
        current_payload.type, inst.words + current_payload.offset,
        inst.words + current_payload.offset + current_payload.num_words);
  }
}

Instruction::Instruction(IRContext* c, spv::Op op, uint32_t ty_id,
                         uint32_t res_id, const OperandList& in_operands)
    : utils::IntrusiveNodeBase<Instruction>(),
      context_(c),
      opcode_(op),
      has_type_id_(ty_id != 0),
      has_result_id_(res_id != 0),
      unique_id_(c->TakeNextUniqueId()),
      operands_(),
      dbg_scope_(kNoDebugScope, kNoInlinedAt) {
  size_t operands_size = in_operands.size();
  if (has_type_id_) {
    operands_size++;
  }
  if (has_result_id_) {
    operands_size++;
  }
  operands_.reserve(operands_size);
  if (has_type_id_) {
    operands_.emplace_back(spv_operand_type_t::SPV_OPERAND_TYPE_TYPE_ID,
                           std::initializer_list<uint32_t>{ty_id});
  }
  if (has_result_id_) {
    operands_.emplace_back(spv_operand_type_t::SPV_OPERAND_TYPE_RESULT_ID,
                           std::initializer_list<uint32_t>{res_id});
  }
  operands_.insert(operands_.end(), in_operands.begin(), in_operands.end());
}

Instruction::Instruction(Instruction&& that)
    : utils::IntrusiveNodeBase<Instruction>(),
      context_(that.context_),
      opcode_(that.opcode_),
      has_type_id_(that.has_type_id_),
      has_result_id_(that.has_result_id_),
      unique_id_(that.unique_id_),
      operands_(std::move(that.operands_)),
      dbg_line_insts_(std::move(that.dbg_line_insts_)),
      dbg_scope_(that.dbg_scope_) {
  for (auto& i : dbg_line_insts_) {
    i.dbg_scope_ = that.dbg_scope_;
  }
}

Instruction& Instruction::operator=(Instruction&& that) {
  context_ = that.context_;
  opcode_ = that.opcode_;
  has_type_id_ = that.has_type_id_;
  has_result_id_ = that.has_result_id_;
  unique_id_ = that.unique_id_;
  operands_ = std::move(that.operands_);
  dbg_line_insts_ = std::move(that.dbg_line_insts_);
  dbg_scope_ = that.dbg_scope_;
  return *this;
}

Instruction* Instruction::Clone(IRContext* c) const {
  Instruction* clone = new Instruction(c);
  clone->opcode_ = opcode_;
  clone->has_type_id_ = has_type_id_;
  clone->has_result_id_ = has_result_id_;
  clone->unique_id_ = c->TakeNextUniqueId();
  clone->operands_ = operands_;
  clone->dbg_line_insts_ = dbg_line_insts_;
  for (auto& i : clone->dbg_line_insts_) {
    i.unique_id_ = c->TakeNextUniqueId();
    if (i.IsDebugLineInst()) i.SetResultId(c->TakeNextId());
  }
  clone->dbg_scope_ = dbg_scope_;
  return clone;
}

uint32_t Instruction::GetSingleWordOperand(uint32_t index) const {
  const auto& words = GetOperand(index).words;
  assert(words.size() == 1 && "expected the operand only taking one word");
  return words.front();
}

uint32_t Instruction::NumInOperandWords() const {
  uint32_t size = 0;
  for (uint32_t i = TypeResultIdCount(); i < operands_.size(); ++i)
    size += static_cast<uint32_t>(operands_[i].words.size());
  return size;
}

bool Instruction::HasBranchWeights() const {
  if (opcode_ == spv::Op::OpBranchConditional &&
      NumOperands() == kOpBranchConditionalWithWeightsNumOperands) {
    return true;
  }

  return false;
}

void Instruction::ToBinaryWithoutAttachedDebugInsts(
    std::vector<uint32_t>* binary) const {
  const uint32_t num_words = 1 + NumOperandWords();
  binary->push_back((num_words << 16) | static_cast<uint16_t>(opcode_));
  for (const auto& operand : operands_) {
    binary->insert(binary->end(), operand.words.begin(), operand.words.end());
  }
}

void Instruction::ReplaceOperands(const OperandList& new_operands) {
  operands_.clear();
  operands_.insert(operands_.begin(), new_operands.begin(), new_operands.end());
}

bool Instruction::IsReadOnlyLoad() const {
  if (IsLoad()) {
    Instruction* address_def = GetBaseAddress();
    if (!address_def) {
      return false;
    }

    if (address_def->opcode() == spv::Op::OpVariable) {
      if (address_def->IsReadOnlyPointer()) {
        return true;
      }
    }

    if (address_def->opcode() == spv::Op::OpLoad) {
      const analysis::Type* address_type =
          context()->get_type_mgr()->GetType(address_def->type_id());
      if (address_type->AsSampledImage() != nullptr) {
        const auto* image_type =
            address_type->AsSampledImage()->image_type()->AsImage();
        if (image_type->sampled() == 1) {
          return true;
        }
      }
    }
  }
  return false;
}

Instruction* Instruction::GetBaseAddress() const {
  uint32_t base = GetSingleWordInOperand(kLoadBaseIndex);
  Instruction* base_inst = context()->get_def_use_mgr()->GetDef(base);
  bool done = false;
  while (!done) {
    switch (base_inst->opcode()) {
      case spv::Op::OpAccessChain:
      case spv::Op::OpInBoundsAccessChain:
      case spv::Op::OpPtrAccessChain:
      case spv::Op::OpInBoundsPtrAccessChain:
      case spv::Op::OpImageTexelPointer:
      case spv::Op::OpCopyObject:
        // All of these instructions have the base pointer use a base pointer
        // in in-operand 0.
        base = base_inst->GetSingleWordInOperand(0);
        base_inst = context()->get_def_use_mgr()->GetDef(base);
        break;
      default:
        done = true;
        break;
    }
  }
  return base_inst;
}

bool Instruction::IsReadOnlyPointer() const {
  if (context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
    return IsReadOnlyPointerShaders();
  else
    return IsReadOnlyPointerKernel();
}

bool Instruction::IsVulkanStorageImage() const {
  if (opcode() != spv::Op::OpTypePointer) {
    return false;
  }

  spv::StorageClass storage_class =
      spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
  if (storage_class != spv::StorageClass::UniformConstant) {
    return false;
  }

  Instruction* base_type =
      context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));

  // Unpack the optional layer of arraying.
  if (base_type->opcode() == spv::Op::OpTypeArray ||
      base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
    base_type = context()->get_def_use_mgr()->GetDef(
        base_type->GetSingleWordInOperand(0));
  }

  if (base_type->opcode() != spv::Op::OpTypeImage) {
    return false;
  }

  if (spv::Dim(base_type->GetSingleWordInOperand(kTypeImageDimIndex)) ==
      spv::Dim::Buffer) {
    return false;
  }

  // Check if the image is sampled.  If we do not know for sure that it is,
  // then assume it is a storage image.
  return base_type->GetSingleWordInOperand(kTypeImageSampledIndex) != 1;
}

bool Instruction::IsVulkanSampledImage() const {
  if (opcode() != spv::Op::OpTypePointer) {
    return false;
  }

  spv::StorageClass storage_class =
      spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
  if (storage_class != spv::StorageClass::UniformConstant) {
    return false;
  }

  Instruction* base_type =
      context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));

  // Unpack the optional layer of arraying.
  if (base_type->opcode() == spv::Op::OpTypeArray ||
      base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
    base_type = context()->get_def_use_mgr()->GetDef(
        base_type->GetSingleWordInOperand(0));
  }

  if (base_type->opcode() != spv::Op::OpTypeImage) {
    return false;
  }

  if (spv::Dim(base_type->GetSingleWordInOperand(kTypeImageDimIndex)) ==
      spv::Dim::Buffer) {
    return false;
  }

  // Check if the image is sampled.  If we know for sure that it is,
  // then return true.
  return base_type->GetSingleWordInOperand(kTypeImageSampledIndex) == 1;
}

bool Instruction::IsVulkanStorageTexelBuffer() const {
  if (opcode() != spv::Op::OpTypePointer) {
    return false;
  }

  spv::StorageClass storage_class =
      spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
  if (storage_class != spv::StorageClass::UniformConstant) {
    return false;
  }

  Instruction* base_type =
      context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));

  // Unpack the optional layer of arraying.
  if (base_type->opcode() == spv::Op::OpTypeArray ||
      base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
    base_type = context()->get_def_use_mgr()->GetDef(
        base_type->GetSingleWordInOperand(0));
  }

  if (base_type->opcode() != spv::Op::OpTypeImage) {
    return false;
  }

  if (spv::Dim(base_type->GetSingleWordInOperand(kTypeImageDimIndex)) !=
      spv::Dim::Buffer) {
    return false;
  }

  // Check if the image is sampled.  If we do not know for sure that it is,
  // then assume it is a storage texel buffer.
  return base_type->GetSingleWordInOperand(kTypeImageSampledIndex) != 1;
}

bool Instruction::IsVulkanStorageBuffer() const {
  // Is there a difference between a "Storage buffer" and a "dynamic storage
  // buffer" in SPIR-V and do we care about the difference?
  if (opcode() != spv::Op::OpTypePointer) {
    return false;
  }

  Instruction* base_type =
      context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));

  // Unpack the optional layer of arraying.
  if (base_type->opcode() == spv::Op::OpTypeArray ||
      base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
    base_type = context()->get_def_use_mgr()->GetDef(
        base_type->GetSingleWordInOperand(0));
  }

  if (base_type->opcode() != spv::Op::OpTypeStruct) {
    return false;
  }

  spv::StorageClass storage_class =
      spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
  if (storage_class == spv::StorageClass::Uniform) {
    bool is_buffer_block = false;
    context()->get_decoration_mgr()->ForEachDecoration(
        base_type->result_id(), uint32_t(spv::Decoration::BufferBlock),
        [&is_buffer_block](const Instruction&) { is_buffer_block = true; });
    return is_buffer_block;
  } else if (storage_class == spv::StorageClass::StorageBuffer) {
    bool is_block = false;
    context()->get_decoration_mgr()->ForEachDecoration(
        base_type->result_id(), uint32_t(spv::Decoration::Block),
        [&is_block](const Instruction&) { is_block = true; });
    return is_block;
  }
  return false;
}

bool Instruction::IsVulkanStorageBufferVariable() const {
  if (opcode() != spv::Op::OpVariable) {
    return false;
  }

  spv::StorageClass storage_class =
      spv::StorageClass(GetSingleWordInOperand(kVariableStorageClassIndex));
  if (storage_class == spv::StorageClass::StorageBuffer ||
      storage_class == spv::StorageClass::Uniform) {
    Instruction* var_type = context()->get_def_use_mgr()->GetDef(type_id());
    return var_type != nullptr && var_type->IsVulkanStorageBuffer();
  }

  return false;
}

bool Instruction::IsVulkanUniformBuffer() const {
  if (opcode() != spv::Op::OpTypePointer) {
    return false;
  }

  spv::StorageClass storage_class =
      spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
  if (storage_class != spv::StorageClass::Uniform) {
    return false;
  }

  Instruction* base_type =
      context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));

  // Unpack the optional layer of arraying.
  if (base_type->opcode() == spv::Op::OpTypeArray ||
      base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
    base_type = context()->get_def_use_mgr()->GetDef(
        base_type->GetSingleWordInOperand(0));
  }

  if (base_type->opcode() != spv::Op::OpTypeStruct) {
    return false;
  }

  bool is_block = false;
  context()->get_decoration_mgr()->ForEachDecoration(
      base_type->result_id(), uint32_t(spv::Decoration::Block),
      [&is_block](const Instruction&) { is_block = true; });
  return is_block;
}

bool Instruction::IsReadOnlyPointerShaders() const {
  if (type_id() == 0) {
    return false;
  }

  Instruction* type_def = context()->get_def_use_mgr()->GetDef(type_id());
  if (type_def->opcode() != spv::Op::OpTypePointer) {
    return false;
  }

  spv::StorageClass storage_class = spv::StorageClass(
      type_def->GetSingleWordInOperand(kPointerTypeStorageClassIndex));

  switch (storage_class) {
    case spv::StorageClass::UniformConstant:
      if (!type_def->IsVulkanStorageImage() &&
          !type_def->IsVulkanStorageTexelBuffer()) {
        return true;
      }
      break;
    case spv::StorageClass::Uniform:
      if (!type_def->IsVulkanStorageBuffer()) {
        return true;
      }
      break;
    case spv::StorageClass::PushConstant:
    case spv::StorageClass::Input:
      return true;
    default:
      break;
  }

  bool is_nonwritable = false;
  context()->get_decoration_mgr()->ForEachDecoration(
      result_id(), uint32_t(spv::Decoration::NonWritable),
      [&is_nonwritable](const Instruction&) { is_nonwritable = true; });
  return is_nonwritable;
}

bool Instruction::IsReadOnlyPointerKernel() const {
  if (type_id() == 0) {
    return false;
  }

  Instruction* type_def = context()->get_def_use_mgr()->GetDef(type_id());
  if (type_def->opcode() != spv::Op::OpTypePointer) {
    return false;
  }

  spv::StorageClass storage_class = spv::StorageClass(
      type_def->GetSingleWordInOperand(kPointerTypeStorageClassIndex));

  return storage_class == spv::StorageClass::UniformConstant;
}

void Instruction::UpdateLexicalScope(uint32_t scope) {
  dbg_scope_.SetLexicalScope(scope);
  for (auto& i : dbg_line_insts_) {
    i.dbg_scope_.SetLexicalScope(scope);
  }
  if (!IsLineInst() &&
      context()->AreAnalysesValid(IRContext::kAnalysisDebugInfo)) {
    context()->get_debug_info_mgr()->AnalyzeDebugInst(this);
  }
}

void Instruction::UpdateDebugInlinedAt(uint32_t new_inlined_at) {
  dbg_scope_.SetInlinedAt(new_inlined_at);
  for (auto& i : dbg_line_insts_) {
    i.dbg_scope_.SetInlinedAt(new_inlined_at);
  }
  if (!IsLineInst() &&
      context()->AreAnalysesValid(IRContext::kAnalysisDebugInfo)) {
    context()->get_debug_info_mgr()->AnalyzeDebugInst(this);
  }
}

void Instruction::ClearDbgLineInsts() {
  if (context()->AreAnalysesValid(IRContext::kAnalysisDefUse)) {
    auto def_use_mgr = context()->get_def_use_mgr();
    for (auto& l_inst : dbg_line_insts_) def_use_mgr->ClearInst(&l_inst);
  }
  clear_dbg_line_insts();
}

void Instruction::UpdateDebugInfoFrom(const Instruction* from) {
  if (from == nullptr) return;
  ClearDbgLineInsts();
  if (!from->dbg_line_insts().empty())
    AddDebugLine(&from->dbg_line_insts().back());
  SetDebugScope(from->GetDebugScope());
  if (!IsLineInst() &&
      context()->AreAnalysesValid(IRContext::kAnalysisDebugInfo)) {
    context()->get_debug_info_mgr()->AnalyzeDebugInst(this);
  }
}

void Instruction::AddDebugLine(const Instruction* inst) {
  dbg_line_insts_.push_back(*inst);
  dbg_line_insts_.back().unique_id_ = context()->TakeNextUniqueId();
  if (inst->IsDebugLineInst())
    dbg_line_insts_.back().SetResultId(context_->TakeNextId());
  if (context()->AreAnalysesValid(IRContext::kAnalysisDefUse))
    context()->get_def_use_mgr()->AnalyzeInstDefUse(&dbg_line_insts_.back());
}

bool Instruction::IsDebugLineInst() const {
  NonSemanticShaderDebugInfo100Instructions ext_opt = GetShader100DebugOpcode();
  return ((ext_opt == NonSemanticShaderDebugInfo100DebugLine) ||
          (ext_opt == NonSemanticShaderDebugInfo100DebugNoLine));
}

bool Instruction::IsLineInst() const { return IsLine() || IsNoLine(); }

bool Instruction::IsLine() const {
  if (opcode() == spv::Op::OpLine) return true;
  NonSemanticShaderDebugInfo100Instructions ext_opt = GetShader100DebugOpcode();
  return ext_opt == NonSemanticShaderDebugInfo100DebugLine;
}

bool Instruction::IsNoLine() const {
  if (opcode() == spv::Op::OpNoLine) return true;
  NonSemanticShaderDebugInfo100Instructions ext_opt = GetShader100DebugOpcode();
  return ext_opt == NonSemanticShaderDebugInfo100DebugNoLine;
}

Instruction* Instruction::InsertBefore(std::unique_ptr<Instruction>&& inst) {
  inst.get()->InsertBefore(this);
  return inst.release();
}

Instruction* Instruction::InsertBefore(
    std::vector<std::unique_ptr<Instruction>>&& list) {
  Instruction* first_node = list.front().get();
  for (auto& inst : list) {
    inst.release()->InsertBefore(this);
  }
  list.clear();
  return first_node;
}

bool Instruction::IsValidBasePointer() const {
  uint32_t tid = type_id();
  if (tid == 0) {
    return false;
  }

  Instruction* type = context()->get_def_use_mgr()->GetDef(tid);
  if (type->opcode() != spv::Op::OpTypePointer) {
    return false;
  }

  auto feature_mgr = context()->get_feature_mgr();
  if (feature_mgr->HasCapability(spv::Capability::Addresses)) {
    // TODO: The rules here could be more restrictive.
    return true;
  }

  if (opcode() == spv::Op::OpVariable ||
      opcode() == spv::Op::OpFunctionParameter) {
    return true;
  }

  // With variable pointers, there are more valid base pointer objects.
  // Variable pointers implicitly declares Variable pointers storage buffer.
  spv::StorageClass storage_class =
      static_cast<spv::StorageClass>(type->GetSingleWordInOperand(0));
  if ((feature_mgr->HasCapability(
           spv::Capability::VariablePointersStorageBuffer) &&
       storage_class == spv::StorageClass::StorageBuffer) ||
      (feature_mgr->HasCapability(spv::Capability::VariablePointers) &&
       storage_class == spv::StorageClass::Workgroup)) {
    switch (opcode()) {
      case spv::Op::OpPhi:
      case spv::Op::OpSelect:
      case spv::Op::OpFunctionCall:
      case spv::Op::OpConstantNull:
        return true;
      default:
        break;
    }
  }

  uint32_t pointee_type_id = type->GetSingleWordInOperand(1);
  Instruction* pointee_type_inst =
      context()->get_def_use_mgr()->GetDef(pointee_type_id);

  if (pointee_type_inst->IsOpaqueType()) {
    return true;
  }
  return false;
}

OpenCLDebugInfo100Instructions Instruction::GetOpenCL100DebugOpcode() const {
  if (opcode() != spv::Op::OpExtInst) {
    return OpenCLDebugInfo100InstructionsMax;
  }

  if (!context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo()) {
    return OpenCLDebugInfo100InstructionsMax;
  }

  if (GetSingleWordInOperand(kExtInstSetIdInIdx) !=
      context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo()) {
    return OpenCLDebugInfo100InstructionsMax;
  }

  return OpenCLDebugInfo100Instructions(
      GetSingleWordInOperand(kExtInstInstructionInIdx));
}

NonSemanticShaderDebugInfo100Instructions Instruction::GetShader100DebugOpcode()
    const {
  if (opcode() != spv::Op::OpExtInst) {
    return NonSemanticShaderDebugInfo100InstructionsMax;
  }

  if (!context()->get_feature_mgr()->GetExtInstImportId_Shader100DebugInfo()) {
    return NonSemanticShaderDebugInfo100InstructionsMax;
  }

  if (GetSingleWordInOperand(kExtInstSetIdInIdx) !=
      context()->get_feature_mgr()->GetExtInstImportId_Shader100DebugInfo()) {
    return NonSemanticShaderDebugInfo100InstructionsMax;
  }

  uint32_t opcode = GetSingleWordInOperand(kExtInstInstructionInIdx);
  if (opcode >= NonSemanticShaderDebugInfo100InstructionsMax) {
    return NonSemanticShaderDebugInfo100InstructionsMax;
  }

  return NonSemanticShaderDebugInfo100Instructions(opcode);
}

CommonDebugInfoInstructions Instruction::GetCommonDebugOpcode() const {
  if (opcode() != spv::Op::OpExtInst) {
    return CommonDebugInfoInstructionsMax;
  }

  const uint32_t opencl_set_id =
      context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo();
  const uint32_t shader_set_id =
      context()->get_feature_mgr()->GetExtInstImportId_Shader100DebugInfo();

  if (!opencl_set_id && !shader_set_id) {
    return CommonDebugInfoInstructionsMax;
  }

  const uint32_t used_set_id = GetSingleWordInOperand(kExtInstSetIdInIdx);

  if (used_set_id != opencl_set_id && used_set_id != shader_set_id) {
    return CommonDebugInfoInstructionsMax;
  }

  return CommonDebugInfoInstructions(
      GetSingleWordInOperand(kExtInstInstructionInIdx));
}

bool Instruction::IsValidBaseImage() const {
  uint32_t tid = type_id();
  if (tid == 0) {
    return false;
  }

  Instruction* type = context()->get_def_use_mgr()->GetDef(tid);
  return (type->opcode() == spv::Op::OpTypeImage ||
          type->opcode() == spv::Op::OpTypeSampledImage);
}

bool Instruction::IsOpaqueType() const {
  if (opcode() == spv::Op::OpTypeStruct) {
    bool is_opaque = false;
    ForEachInOperand([&is_opaque, this](const uint32_t* op_id) {
      Instruction* type_inst = context()->get_def_use_mgr()->GetDef(*op_id);
      is_opaque |= type_inst->IsOpaqueType();
    });
    return is_opaque;
  } else if (opcode() == spv::Op::OpTypeArray) {
    uint32_t sub_type_id = GetSingleWordInOperand(0);
    Instruction* sub_type_inst =
        context()->get_def_use_mgr()->GetDef(sub_type_id);
    return sub_type_inst->IsOpaqueType();
  } else {
    return opcode() == spv::Op::OpTypeRuntimeArray ||
           spvOpcodeIsBaseOpaqueType(opcode());
  }
}

bool Instruction::IsFoldable() const {
  return IsFoldableByFoldScalar() || IsFoldableByFoldVector() ||
         context()->get_instruction_folder().HasConstFoldingRule(this);
}

bool Instruction::IsFoldableByFoldScalar() const {
  const InstructionFolder& folder = context()->get_instruction_folder();
  if (!folder.IsFoldableOpcode(opcode())) {
    return false;
  }

  Instruction* type = context()->get_def_use_mgr()->GetDef(type_id());
  if (!folder.IsFoldableScalarType(type)) {
    return false;
  }

  // Even if the type of the instruction is foldable, its operands may not be
  // foldable (e.g., comparisons of 64bit types).  Check that all operand types
  // are foldable before accepting the instruction.
  return WhileEachInOperand([&folder, this](const uint32_t* op_id) {
    Instruction* def_inst = context()->get_def_use_mgr()->GetDef(*op_id);
    Instruction* def_inst_type =
        context()->get_def_use_mgr()->GetDef(def_inst->type_id());
    return folder.IsFoldableScalarType(def_inst_type);
  });
}

bool Instruction::IsFoldableByFoldVector() const {
  const InstructionFolder& folder = context()->get_instruction_folder();
  if (!folder.IsFoldableOpcode(opcode())) {
    return false;
  }

  Instruction* type = context()->get_def_use_mgr()->GetDef(type_id());
  if (!folder.IsFoldableVectorType(type)) {
    return false;
  }

  // Even if the type of the instruction is foldable, its operands may not be
  // foldable (e.g., comparisons of 64bit types).  Check that all operand types
  // are foldable before accepting the instruction.
  return WhileEachInOperand([&folder, this](const uint32_t* op_id) {
    Instruction* def_inst = context()->get_def_use_mgr()->GetDef(*op_id);
    Instruction* def_inst_type =
        context()->get_def_use_mgr()->GetDef(def_inst->type_id());
    return folder.IsFoldableVectorType(def_inst_type);
  });
}

bool Instruction::IsFloatingPointFoldingAllowed() const {
  // TODO: Add the rules for kernels.  For now it will be pessimistic.
  // For now, do not support capabilities introduced by SPV_KHR_float_controls.
  if (!context_->get_feature_mgr()->HasCapability(spv::Capability::Shader) ||
      context_->get_feature_mgr()->HasCapability(
          spv::Capability::DenormPreserve) ||
      context_->get_feature_mgr()->HasCapability(
          spv::Capability::DenormFlushToZero) ||
      context_->get_feature_mgr()->HasCapability(
          spv::Capability::SignedZeroInfNanPreserve) ||
      context_->get_feature_mgr()->HasCapability(
          spv::Capability::RoundingModeRTZ) ||
      context_->get_feature_mgr()->HasCapability(
          spv::Capability::RoundingModeRTE)) {
    return false;
  }

  bool is_nocontract = false;
  context_->get_decoration_mgr()->WhileEachDecoration(
      result_id(), uint32_t(spv::Decoration::NoContraction),
      [&is_nocontract](const Instruction&) {
        is_nocontract = true;
        return false;
      });
  return !is_nocontract;
}

std::string Instruction::PrettyPrint(uint32_t options) const {
  // Convert the module to binary.
  std::vector<uint32_t> module_binary;
  context()->module()->ToBinary(&module_binary, /* skip_nop = */ false);

  // Convert the instruction to binary. This is used to identify the correct
  // stream of words to output from the module.
  std::vector<uint32_t> inst_binary;
  ToBinaryWithoutAttachedDebugInsts(&inst_binary);

  // Do not generate a header.
  return spvInstructionBinaryToText(
      context()->grammar().target_env(), inst_binary.data(), inst_binary.size(),
      module_binary.data(), module_binary.size(),
      options | SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
}

std::ostream& operator<<(std::ostream& str, const Instruction& inst) {
  str << inst.PrettyPrint();
  return str;
}

void Instruction::Dump() const {
  std::cerr << "Instruction #" << unique_id() << "\n" << *this << "\n";
}

bool Instruction::IsOpcodeCodeMotionSafe() const {
  switch (opcode_) {
    case spv::Op::OpNop:
    case spv::Op::OpUndef:
    case spv::Op::OpLoad:
    case spv::Op::OpAccessChain:
    case spv::Op::OpInBoundsAccessChain:
    case spv::Op::OpArrayLength:
    case spv::Op::OpVectorExtractDynamic:
    case spv::Op::OpVectorInsertDynamic:
    case spv::Op::OpVectorShuffle:
    case spv::Op::OpCompositeConstruct:
    case spv::Op::OpCompositeExtract:
    case spv::Op::OpCompositeInsert:
    case spv::Op::OpCopyObject:
    case spv::Op::OpTranspose:
    case spv::Op::OpConvertFToU:
    case spv::Op::OpConvertFToS:
    case spv::Op::OpConvertSToF:
    case spv::Op::OpConvertUToF:
    case spv::Op::OpUConvert:
    case spv::Op::OpSConvert:
    case spv::Op::OpFConvert:
    case spv::Op::OpQuantizeToF16:
    case spv::Op::OpBitcast:
    case spv::Op::OpSNegate:
    case spv::Op::OpFNegate:
    case spv::Op::OpIAdd:
    case spv::Op::OpFAdd:
    case spv::Op::OpISub:
    case spv::Op::OpFSub:
    case spv::Op::OpIMul:
    case spv::Op::OpFMul:
    case spv::Op::OpUDiv:
    case spv::Op::OpSDiv:
    case spv::Op::OpFDiv:
    case spv::Op::OpUMod:
    case spv::Op::OpSRem:
    case spv::Op::OpSMod:
    case spv::Op::OpFRem:
    case spv::Op::OpFMod:
    case spv::Op::OpVectorTimesScalar:
    case spv::Op::OpMatrixTimesScalar:
    case spv::Op::OpVectorTimesMatrix:
    case spv::Op::OpMatrixTimesVector:
    case spv::Op::OpMatrixTimesMatrix:
    case spv::Op::OpOuterProduct:
    case spv::Op::OpDot:
    case spv::Op::OpIAddCarry:
    case spv::Op::OpISubBorrow:
    case spv::Op::OpUMulExtended:
    case spv::Op::OpSMulExtended:
    case spv::Op::OpAny:
    case spv::Op::OpAll:
    case spv::Op::OpIsNan:
    case spv::Op::OpIsInf:
    case spv::Op::OpLogicalEqual:
    case spv::Op::OpLogicalNotEqual:
    case spv::Op::OpLogicalOr:
    case spv::Op::OpLogicalAnd:
    case spv::Op::OpLogicalNot:
    case spv::Op::OpSelect:
    case spv::Op::OpIEqual:
    case spv::Op::OpINotEqual:
    case spv::Op::OpUGreaterThan:
    case spv::Op::OpSGreaterThan:
    case spv::Op::OpUGreaterThanEqual:
    case spv::Op::OpSGreaterThanEqual:
    case spv::Op::OpULessThan:
    case spv::Op::OpSLessThan:
    case spv::Op::OpULessThanEqual:
    case spv::Op::OpSLessThanEqual:
    case spv::Op::OpFOrdEqual:
    case spv::Op::OpFUnordEqual:
    case spv::Op::OpFOrdNotEqual:
    case spv::Op::OpFUnordNotEqual:
    case spv::Op::OpFOrdLessThan:
    case spv::Op::OpFUnordLessThan:
    case spv::Op::OpFOrdGreaterThan:
    case spv::Op::OpFUnordGreaterThan:
    case spv::Op::OpFOrdLessThanEqual:
    case spv::Op::OpFUnordLessThanEqual:
    case spv::Op::OpFOrdGreaterThanEqual:
    case spv::Op::OpFUnordGreaterThanEqual:
    case spv::Op::OpShiftRightLogical:
    case spv::Op::OpShiftRightArithmetic:
    case spv::Op::OpShiftLeftLogical:
    case spv::Op::OpBitwiseOr:
    case spv::Op::OpBitwiseXor:
    case spv::Op::OpBitwiseAnd:
    case spv::Op::OpNot:
    case spv::Op::OpBitFieldInsert:
    case spv::Op::OpBitFieldSExtract:
    case spv::Op::OpBitFieldUExtract:
    case spv::Op::OpBitReverse:
    case spv::Op::OpBitCount:
    case spv::Op::OpSizeOf:
      return true;
    default:
      return false;
  }
}

bool Instruction::IsScalarizable() const {
  if (spvOpcodeIsScalarizable(opcode())) {
    return true;
  }

  if (opcode() == spv::Op::OpExtInst) {
    uint32_t instSetId =
        context()->get_feature_mgr()->GetExtInstImportId_GLSLstd450();

    if (GetSingleWordInOperand(kExtInstSetIdInIdx) == instSetId) {
      switch (GetSingleWordInOperand(kExtInstInstructionInIdx)) {
        case GLSLstd450Round:
        case GLSLstd450RoundEven:
        case GLSLstd450Trunc:
        case GLSLstd450FAbs:
        case GLSLstd450SAbs:
        case GLSLstd450FSign:
        case GLSLstd450SSign:
        case GLSLstd450Floor:
        case GLSLstd450Ceil:
        case GLSLstd450Fract:
        case GLSLstd450Radians:
        case GLSLstd450Degrees:
        case GLSLstd450Sin:
        case GLSLstd450Cos:
        case GLSLstd450Tan:
        case GLSLstd450Asin:
        case GLSLstd450Acos:
        case GLSLstd450Atan:
        case GLSLstd450Sinh:
        case GLSLstd450Cosh:
        case GLSLstd450Tanh:
        case GLSLstd450Asinh:
        case GLSLstd450Acosh:
        case GLSLstd450Atanh:
        case GLSLstd450Atan2:
        case GLSLstd450Pow:
        case GLSLstd450Exp:
        case GLSLstd450Log:
        case GLSLstd450Exp2:
        case GLSLstd450Log2:
        case GLSLstd450Sqrt:
        case GLSLstd450InverseSqrt:
        case GLSLstd450Modf:
        case GLSLstd450FMin:
        case GLSLstd450UMin:
        case GLSLstd450SMin:
        case GLSLstd450FMax:
        case GLSLstd450UMax:
        case GLSLstd450SMax:
        case GLSLstd450FClamp:
        case GLSLstd450UClamp:
        case GLSLstd450SClamp:
        case GLSLstd450FMix:
        case GLSLstd450Step:
        case GLSLstd450SmoothStep:
        case GLSLstd450Fma:
        case GLSLstd450Frexp:
        case GLSLstd450Ldexp:
        case GLSLstd450FindILsb:
        case GLSLstd450FindSMsb:
        case GLSLstd450FindUMsb:
        case GLSLstd450NMin:
        case GLSLstd450NMax:
        case GLSLstd450NClamp:
          return true;
        default:
          return false;
      }
    }
  }
  return false;
}

bool Instruction::IsOpcodeSafeToDelete() const {
  if (context()->IsCombinatorInstruction(this)) {
    return true;
  }

  switch (opcode()) {
    case spv::Op::OpDPdx:
    case spv::Op::OpDPdy:
    case spv::Op::OpFwidth:
    case spv::Op::OpDPdxFine:
    case spv::Op::OpDPdyFine:
    case spv::Op::OpFwidthFine:
    case spv::Op::OpDPdxCoarse:
    case spv::Op::OpDPdyCoarse:
    case spv::Op::OpFwidthCoarse:
    case spv::Op::OpImageQueryLod:
      return true;
    default:
      return false;
  }
}

bool Instruction::IsNonSemanticInstruction() const {
  if (!HasResultId()) return false;
  if (opcode() != spv::Op::OpExtInst) return false;

  auto import_inst =
      context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(0));
  std::string import_name = import_inst->GetInOperand(0).AsString();
  return import_name.find("NonSemantic.") == 0;
}

void DebugScope::ToBinary(uint32_t type_id, uint32_t result_id,
                          uint32_t ext_set,
                          std::vector<uint32_t>* binary) const {
  uint32_t num_words = kDebugScopeNumWords;
  CommonDebugInfoInstructions dbg_opcode = CommonDebugInfoDebugScope;
  if (GetLexicalScope() == kNoDebugScope) {
    num_words = kDebugNoScopeNumWords;
    dbg_opcode = CommonDebugInfoDebugNoScope;
  } else if (GetInlinedAt() == kNoInlinedAt) {
    num_words = kDebugScopeNumWordsWithoutInlinedAt;
  }
  std::vector<uint32_t> operands = {
      (num_words << 16) | static_cast<uint16_t>(spv::Op::OpExtInst),
      type_id,
      result_id,
      ext_set,
      static_cast<uint32_t>(dbg_opcode),
  };
  binary->insert(binary->end(), operands.begin(), operands.end());
  if (GetLexicalScope() != kNoDebugScope) {
    binary->push_back(GetLexicalScope());
    if (GetInlinedAt() != kNoInlinedAt) binary->push_back(GetInlinedAt());
  }
}

}  // namespace opt
}  // namespace spvtools
