// 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
// 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()) {
      uint32_t new_id = c->TakeNextId();
      if (new_id == 0) {
        return nullptr;
      }
      i.SetResultId(new_id);
    }
  }
  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::OpUntypedAccessChainKHR:
      case spv::Op::OpPtrAccessChain:
      case spv::Op::OpInBoundsPtrAccessChain:
      case spv::Op::OpImageTexelPointer:
      case spv::Op::OpCopyObject:
        // All of these instructions have their 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();
}

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

bool Instruction::AddDebugLine(const Instruction* inst) {
  dbg_line_insts_.push_back(*inst);
  dbg_line_insts_.back().unique_id_ = context()->TakeNextUniqueId();
  if (inst->IsDebugLineInst()) {
    uint32_t new_id = context()->TakeNextId();
    if (new_id == 0) {
      return false;
    }
    dbg_line_insts_.back().SetResultId(new_id);
  }
  if (context()->AreAnalysesValid(IRContext::kAnalysisDefUse))
    context()->get_def_use_mgr()->AnalyzeInstDefUse(&dbg_line_insts_.back());
  return true;
}

bool Instruction::IsDebugLineInst() const {
  NonSemanticShaderDebugInfo100Instructions ext_opt = GetShaderDebugOpcode();
  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 = GetShaderDebugOpcode();
  return ext_opt == NonSemanticShaderDebugInfo100DebugLine;
}

bool Instruction::IsNoLine() const {
  if (opcode() == spv::Op::OpNoLine) return true;
  NonSemanticShaderDebugInfo100Instructions ext_opt = GetShaderDebugOpcode();
  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::GetShaderDebugOpcode()
    const {
  if (opcode() != spv::Op::OpExtInst) {
    return NonSemanticShaderDebugInfo100InstructionsMax;
  }

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

  if (GetSingleWordInOperand(kExtInstSetIdInIdx) !=
      context()->get_feature_mgr()->GetExtInstImportId_ShaderDebugInfo()) {
    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_ShaderDebugInfo();

  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 WhileEachInId([&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 WhileEachInId([&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;
  }

  if (IsNonSemanticInstruction() &&
      (GetShaderDebugOpcode() == NonSemanticShaderDebugInfo100DebugDeclare ||
       GetShaderDebugOpcode() == NonSemanticShaderDebugInfo100DebugValue)) {
    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
