// Copyright (c) 2020-2022 Google LLC
// Copyright (c) 2022 LunarG 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/debug_info_manager.h"

#include <cassert>

#include "source/opt/ir_context.h"

// Constants for OpenCL.DebugInfo.100 & NonSemantic.Shader.DebugInfo.100
// extension instructions.

static const uint32_t kOpLineOperandLineIndex = 1;
static const uint32_t kLineOperandIndexDebugFunction = 7;
static const uint32_t kLineOperandIndexDebugLexicalBlock = 5;
static const uint32_t kLineOperandIndexDebugLine = 5;
static const uint32_t kConstanstOperandIndexLiteral = 2;
static const uint32_t kDebugFunctionOperandFunctionIndex = 13;
static const uint32_t kDebugFunctionDefinitionOperandDebugFunctionIndex = 4;
static const uint32_t kDebugFunctionDefinitionOperandOpFunctionIndex = 5;
static const uint32_t kDebugFunctionOperandParentIndex = 9;
static const uint32_t kDebugTypeCompositeOperandParentIndex = 9;
static const uint32_t kDebugLexicalBlockOperandParentIndex = 7;
static const uint32_t kDebugInlinedAtOperandInlinedIndex = 6;
static const uint32_t kDebugExpressOperandOperationIndex = 4;
static const uint32_t kDebugDeclareOperandLocalVariableIndex = 4;
static const uint32_t kDebugDeclareOperandVariableIndex = 5;
static const uint32_t kDebugValueOperandExpressionIndex = 6;
static const uint32_t kDebugOperationOperandOperationIndex = 4;
static const uint32_t kOpVariableOperandStorageClassIndex = 2;
static const uint32_t kDebugLocalVariableOperandParentIndex = 9;
static const uint32_t kExtInstInstructionInIdx = 1;
static const uint32_t kDebugGlobalVariableOperandFlagsIndex = 12;
static const uint32_t kDebugLocalVariableOperandFlagsIndex = 10;

namespace spvtools {
namespace opt {
namespace analysis {
namespace {

void SetInlinedOperand(Instruction* dbg_inlined_at, uint32_t inlined_operand) {
  assert(dbg_inlined_at);
  assert(dbg_inlined_at->GetCommonDebugOpcode() ==
         CommonDebugInfoDebugInlinedAt);
  if (dbg_inlined_at->NumOperands() <= kDebugInlinedAtOperandInlinedIndex) {
    dbg_inlined_at->AddOperand(
        {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {inlined_operand}});
  } else {
    dbg_inlined_at->SetOperand(kDebugInlinedAtOperandInlinedIndex,
                               {inlined_operand});
  }
}

uint32_t GetInlinedOperand(Instruction* dbg_inlined_at) {
  assert(dbg_inlined_at);
  assert(dbg_inlined_at->GetCommonDebugOpcode() ==
         CommonDebugInfoDebugInlinedAt);
  if (dbg_inlined_at->NumOperands() <= kDebugInlinedAtOperandInlinedIndex)
    return kNoInlinedAt;
  return dbg_inlined_at->GetSingleWordOperand(
      kDebugInlinedAtOperandInlinedIndex);
}

bool IsEmptyDebugExpression(Instruction* instr) {
  return (instr->GetCommonDebugOpcode() == CommonDebugInfoDebugExpression) &&
         instr->NumOperands() == kDebugExpressOperandOperationIndex;
}

}  // namespace

DebugInfoManager::DebugInfoManager(IRContext* c) : context_(c) {
  AnalyzeDebugInsts(*c->module());
}

uint32_t DebugInfoManager::GetDbgSetImportId() {
  uint32_t setId =
      context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo();
  if (setId == 0) {
    setId =
        context()->get_feature_mgr()->GetExtInstImportId_Shader100DebugInfo();
  }
  return setId;
}

Instruction* DebugInfoManager::GetDbgInst(uint32_t id) {
  auto dbg_inst_it = id_to_dbg_inst_.find(id);
  return dbg_inst_it == id_to_dbg_inst_.end() ? nullptr : dbg_inst_it->second;
}

void DebugInfoManager::RegisterDbgInst(Instruction* inst) {
  assert(inst->NumInOperands() != 0 &&
         (GetDbgSetImportId() == inst->GetInOperand(0).words[0]) &&
         "Given instruction is not a debug instruction");
  id_to_dbg_inst_[inst->result_id()] = inst;
}

void DebugInfoManager::RegisterDbgFunction(Instruction* inst) {
  if (inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugFunction) {
    auto fn_id = inst->GetSingleWordOperand(kDebugFunctionOperandFunctionIndex);
    // Do not register function that has been optimized away.
    auto fn_inst = GetDbgInst(fn_id);
    if (fn_inst != nullptr) {
      assert(GetDbgInst(fn_id)->GetOpenCL100DebugOpcode() ==
             OpenCLDebugInfo100DebugInfoNone);
      return;
    }
    assert(
        fn_id_to_dbg_fn_.find(fn_id) == fn_id_to_dbg_fn_.end() &&
        "Register DebugFunction for a function that already has DebugFunction");
    fn_id_to_dbg_fn_[fn_id] = inst;
  } else if (inst->GetShader100DebugOpcode() ==
             NonSemanticShaderDebugInfo100DebugFunctionDefinition) {
    auto fn_id = inst->GetSingleWordOperand(
        kDebugFunctionDefinitionOperandOpFunctionIndex);
    auto fn_inst = GetDbgInst(inst->GetSingleWordOperand(
        kDebugFunctionDefinitionOperandDebugFunctionIndex));
    assert(fn_inst && fn_inst->GetShader100DebugOpcode() ==
                          NonSemanticShaderDebugInfo100DebugFunction);
    assert(fn_id_to_dbg_fn_.find(fn_id) == fn_id_to_dbg_fn_.end() &&
           "Register DebugFunctionDefinition for a function that already has "
           "DebugFunctionDefinition");
    fn_id_to_dbg_fn_[fn_id] = fn_inst;
  } else {
    assert(false && "inst is not a DebugFunction");
  }
}

void DebugInfoManager::RegisterDbgDeclare(uint32_t var_id,
                                          Instruction* dbg_declare) {
  assert(dbg_declare->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare ||
         dbg_declare->GetCommonDebugOpcode() == CommonDebugInfoDebugValue);
  auto dbg_decl_itr = var_id_to_dbg_decl_.find(var_id);
  if (dbg_decl_itr == var_id_to_dbg_decl_.end()) {
    var_id_to_dbg_decl_[var_id] = {dbg_declare};
  } else {
    dbg_decl_itr->second.insert(dbg_declare);
  }
}

// Create new constant directly into global value area, bypassing the
// Constant manager. This is used when the DefUse or Constant managers
// are invalid and cannot be regenerated due to the module being in an
// inconsistent state e.g. in the middle of significant modification
// such as inlining. Invalidate Constant and DefUse managers if used.
uint32_t AddNewConstInGlobals(IRContext* context, uint32_t const_value) {
  uint32_t id = context->TakeNextId();
  std::unique_ptr<Instruction> new_const(new Instruction(
      context, SpvOpConstant, context->get_type_mgr()->GetUIntTypeId(), id,
      {
          {spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
           {const_value}},
      }));
  context->module()->AddGlobalValue(std::move(new_const));
  context->InvalidateAnalyses(IRContext::kAnalysisConstants);
  context->InvalidateAnalyses(IRContext::kAnalysisDefUse);
  return id;
}

uint32_t DebugInfoManager::CreateDebugInlinedAt(const Instruction* line,
                                                const DebugScope& scope) {
  uint32_t setId = GetDbgSetImportId();

  if (setId == 0) return kNoInlinedAt;

  spv_operand_type_t line_number_type =
      spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER;

  // In NonSemantic.Shader.DebugInfo.100, all constants are IDs of OpConstant,
  // not literals.
  if (setId ==
      context()->get_feature_mgr()->GetExtInstImportId_Shader100DebugInfo())
    line_number_type = spv_operand_type_t::SPV_OPERAND_TYPE_ID;

  uint32_t line_number = 0;
  if (line == nullptr) {
    auto* lexical_scope_inst = GetDbgInst(scope.GetLexicalScope());
    if (lexical_scope_inst == nullptr) return kNoInlinedAt;
    CommonDebugInfoInstructions debug_opcode =
        lexical_scope_inst->GetCommonDebugOpcode();
    switch (debug_opcode) {
      case CommonDebugInfoDebugFunction:
        line_number = lexical_scope_inst->GetSingleWordOperand(
            kLineOperandIndexDebugFunction);
        break;
      case CommonDebugInfoDebugLexicalBlock:
        line_number = lexical_scope_inst->GetSingleWordOperand(
            kLineOperandIndexDebugLexicalBlock);
        break;
      case CommonDebugInfoDebugTypeComposite:
      case CommonDebugInfoDebugCompilationUnit:
        assert(false &&
               "DebugTypeComposite and DebugCompilationUnit are lexical "
               "scopes, but we inline functions into a function or a block "
               "of a function, not into a struct/class or a global scope.");
        break;
      default:
        assert(false &&
               "Unreachable. a debug extension instruction for a "
               "lexical scope must be DebugFunction, DebugTypeComposite, "
               "DebugLexicalBlock, or DebugCompilationUnit.");
        break;
    }
  } else {
    if (line->opcode() == SpvOpLine) {
      line_number = line->GetSingleWordOperand(kOpLineOperandLineIndex);
    } else if (line->GetShader100DebugOpcode() ==
               NonSemanticShaderDebugInfo100DebugLine) {
      auto const line_number_id =
          line->GetSingleWordOperand(kLineOperandIndexDebugLine);
      auto const line_number_inst =
          context()->get_def_use_mgr()->GetDef(line_number_id);
      line_number =
          line_number_inst->GetSingleWordOperand(kConstanstOperandIndexLiteral);
    } else {
      assert(false &&
             "Unreachable. A line instruction must be OpLine or DebugLine");
    }

    // If we need the line number as an ID, generate that constant now.
    // If Constant or DefUse managers are invalid, generate constant
    // directly into the global value section of the module; do not
    // use Constant manager which may attempt to invoke building of the
    // DefUse manager which cannot be done during inlining. The extra
    // constants that may be generated here is likely not significant
    // and will likely be cleaned up in later passes.
    if (line_number_type == spv_operand_type_t::SPV_OPERAND_TYPE_ID) {
      if (!context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse) ||
          !context()->AreAnalysesValid(IRContext::Analysis::kAnalysisConstants))
        line_number = AddNewConstInGlobals(context(), line_number);
      else
        line_number = context()->get_constant_mgr()->GetUIntConst(line_number);
    }
  }

  uint32_t result_id = context()->TakeNextId();
  std::unique_ptr<Instruction> inlined_at(new Instruction(
      context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
      result_id,
      {
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {setId}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
           {static_cast<uint32_t>(CommonDebugInfoDebugInlinedAt)}},
          {line_number_type, {line_number}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {scope.GetLexicalScope()}},
      }));
  // |scope| already has DebugInlinedAt. We put the existing DebugInlinedAt
  // into the Inlined operand of this new DebugInlinedAt.
  if (scope.GetInlinedAt() != kNoInlinedAt) {
    inlined_at->AddOperand(
        {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {scope.GetInlinedAt()}});
  }
  RegisterDbgInst(inlined_at.get());
  if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
    context()->get_def_use_mgr()->AnalyzeInstDefUse(inlined_at.get());
  context()->module()->AddExtInstDebugInfo(std::move(inlined_at));
  return result_id;
}

DebugScope DebugInfoManager::BuildDebugScope(
    const DebugScope& callee_instr_scope,
    DebugInlinedAtContext* inlined_at_ctx) {
  return DebugScope(callee_instr_scope.GetLexicalScope(),
                    BuildDebugInlinedAtChain(callee_instr_scope.GetInlinedAt(),
                                             inlined_at_ctx));
}

uint32_t DebugInfoManager::BuildDebugInlinedAtChain(
    uint32_t callee_inlined_at, DebugInlinedAtContext* inlined_at_ctx) {
  if (inlined_at_ctx->GetScopeOfCallInstruction().GetLexicalScope() ==
      kNoDebugScope)
    return kNoInlinedAt;

  // Reuse the already generated DebugInlinedAt chain if exists.
  uint32_t already_generated_chain_head_id =
      inlined_at_ctx->GetDebugInlinedAtChain(callee_inlined_at);
  if (already_generated_chain_head_id != kNoInlinedAt) {
    return already_generated_chain_head_id;
  }

  const uint32_t new_dbg_inlined_at_id =
      CreateDebugInlinedAt(inlined_at_ctx->GetLineOfCallInstruction(),
                           inlined_at_ctx->GetScopeOfCallInstruction());
  if (new_dbg_inlined_at_id == kNoInlinedAt) return kNoInlinedAt;

  if (callee_inlined_at == kNoInlinedAt) {
    inlined_at_ctx->SetDebugInlinedAtChain(kNoInlinedAt, new_dbg_inlined_at_id);
    return new_dbg_inlined_at_id;
  }

  uint32_t chain_head_id = kNoInlinedAt;
  uint32_t chain_iter_id = callee_inlined_at;
  Instruction* last_inlined_at_in_chain = nullptr;
  do {
    Instruction* new_inlined_at_in_chain = CloneDebugInlinedAt(
        chain_iter_id, /* insert_before */ last_inlined_at_in_chain);
    assert(new_inlined_at_in_chain != nullptr);

    // Set DebugInlinedAt of the new scope as the head of the chain.
    if (chain_head_id == kNoInlinedAt)
      chain_head_id = new_inlined_at_in_chain->result_id();

    // Previous DebugInlinedAt of the chain must point to the new
    // DebugInlinedAt as its Inlined operand to build a recursive
    // chain.
    if (last_inlined_at_in_chain != nullptr) {
      SetInlinedOperand(last_inlined_at_in_chain,
                        new_inlined_at_in_chain->result_id());
    }
    last_inlined_at_in_chain = new_inlined_at_in_chain;

    chain_iter_id = GetInlinedOperand(new_inlined_at_in_chain);
  } while (chain_iter_id != kNoInlinedAt);

  // Put |new_dbg_inlined_at_id| into the end of the chain.
  SetInlinedOperand(last_inlined_at_in_chain, new_dbg_inlined_at_id);

  // Keep the new chain information that will be reused it.
  inlined_at_ctx->SetDebugInlinedAtChain(callee_inlined_at, chain_head_id);
  return chain_head_id;
}

Instruction* DebugInfoManager::GetDebugOperationWithDeref() {
  if (deref_operation_ != nullptr) return deref_operation_;

  uint32_t result_id = context()->TakeNextId();
  std::unique_ptr<Instruction> deref_operation;

  if (context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo()) {
    deref_operation = std::unique_ptr<Instruction>(new Instruction(
        context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
        result_id,
        {
            {SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
            {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
             {static_cast<uint32_t>(OpenCLDebugInfo100DebugOperation)}},
            {SPV_OPERAND_TYPE_CLDEBUG100_DEBUG_OPERATION,
             {static_cast<uint32_t>(OpenCLDebugInfo100Deref)}},
        }));
  } else {
    uint32_t deref_id = context()->get_constant_mgr()->GetUIntConst(
        NonSemanticShaderDebugInfo100Deref);

    deref_operation = std::unique_ptr<Instruction>(
        new Instruction(context(), SpvOpExtInst,
                        context()->get_type_mgr()->GetVoidTypeId(), result_id,
                        {
                            {SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
                            {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
                             {static_cast<uint32_t>(
                                 NonSemanticShaderDebugInfo100DebugOperation)}},
                            {SPV_OPERAND_TYPE_ID, {deref_id}},
                        }));
  }

  // Add to the front of |ext_inst_debuginfo_|.
  deref_operation_ =
      context()->module()->ext_inst_debuginfo_begin()->InsertBefore(
          std::move(deref_operation));

  RegisterDbgInst(deref_operation_);
  if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
    context()->get_def_use_mgr()->AnalyzeInstDefUse(deref_operation_);
  return deref_operation_;
}

Instruction* DebugInfoManager::DerefDebugExpression(Instruction* dbg_expr) {
  assert(dbg_expr->GetCommonDebugOpcode() == CommonDebugInfoDebugExpression);
  std::unique_ptr<Instruction> deref_expr(dbg_expr->Clone(context()));
  deref_expr->SetResultId(context()->TakeNextId());
  deref_expr->InsertOperand(
      kDebugExpressOperandOperationIndex,
      {SPV_OPERAND_TYPE_ID, {GetDebugOperationWithDeref()->result_id()}});
  auto* deref_expr_instr =
      context()->ext_inst_debuginfo_end()->InsertBefore(std::move(deref_expr));
  AnalyzeDebugInst(deref_expr_instr);
  if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
    context()->get_def_use_mgr()->AnalyzeInstDefUse(deref_expr_instr);
  return deref_expr_instr;
}

Instruction* DebugInfoManager::GetDebugInfoNone() {
  if (debug_info_none_inst_ != nullptr) return debug_info_none_inst_;

  uint32_t result_id = context()->TakeNextId();
  std::unique_ptr<Instruction> dbg_info_none_inst(new Instruction(
      context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
      result_id,
      {
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
           {static_cast<uint32_t>(CommonDebugInfoDebugInfoNone)}},
      }));

  // Add to the front of |ext_inst_debuginfo_|.
  debug_info_none_inst_ =
      context()->module()->ext_inst_debuginfo_begin()->InsertBefore(
          std::move(dbg_info_none_inst));

  RegisterDbgInst(debug_info_none_inst_);
  if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
    context()->get_def_use_mgr()->AnalyzeInstDefUse(debug_info_none_inst_);
  return debug_info_none_inst_;
}

Instruction* DebugInfoManager::GetEmptyDebugExpression() {
  if (empty_debug_expr_inst_ != nullptr) return empty_debug_expr_inst_;

  uint32_t result_id = context()->TakeNextId();
  std::unique_ptr<Instruction> empty_debug_expr(new Instruction(
      context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
      result_id,
      {
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
           {static_cast<uint32_t>(CommonDebugInfoDebugExpression)}},
      }));

  // Add to the front of |ext_inst_debuginfo_|.
  empty_debug_expr_inst_ =
      context()->module()->ext_inst_debuginfo_begin()->InsertBefore(
          std::move(empty_debug_expr));

  RegisterDbgInst(empty_debug_expr_inst_);
  if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
    context()->get_def_use_mgr()->AnalyzeInstDefUse(empty_debug_expr_inst_);
  return empty_debug_expr_inst_;
}

Instruction* DebugInfoManager::GetDebugInlinedAt(uint32_t dbg_inlined_at_id) {
  auto* inlined_at = GetDbgInst(dbg_inlined_at_id);
  if (inlined_at == nullptr) return nullptr;
  if (inlined_at->GetCommonDebugOpcode() != CommonDebugInfoDebugInlinedAt) {
    return nullptr;
  }
  return inlined_at;
}

Instruction* DebugInfoManager::CloneDebugInlinedAt(uint32_t clone_inlined_at_id,
                                                   Instruction* insert_before) {
  auto* inlined_at = GetDebugInlinedAt(clone_inlined_at_id);
  if (inlined_at == nullptr) return nullptr;
  std::unique_ptr<Instruction> new_inlined_at(inlined_at->Clone(context()));
  new_inlined_at->SetResultId(context()->TakeNextId());
  RegisterDbgInst(new_inlined_at.get());
  if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
    context()->get_def_use_mgr()->AnalyzeInstDefUse(new_inlined_at.get());
  if (insert_before != nullptr)
    return insert_before->InsertBefore(std::move(new_inlined_at));
  return context()->module()->ext_inst_debuginfo_end()->InsertBefore(
      std::move(new_inlined_at));
}

bool DebugInfoManager::IsVariableDebugDeclared(uint32_t variable_id) {
  auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id);
  return dbg_decl_itr != var_id_to_dbg_decl_.end();
}

bool DebugInfoManager::KillDebugDeclares(uint32_t variable_id) {
  bool modified = false;
  auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id);
  if (dbg_decl_itr != var_id_to_dbg_decl_.end()) {
    // We intentionally copy the list of DebugDeclare instructions because
    // context()->KillInst(dbg_decl) will update |var_id_to_dbg_decl_|. If we
    // directly use |dbg_decl_itr->second|, it accesses a dangling pointer.
    auto copy_dbg_decls = dbg_decl_itr->second;

    for (auto* dbg_decl : copy_dbg_decls) {
      context()->KillInst(dbg_decl);
      modified = true;
    }
    var_id_to_dbg_decl_.erase(dbg_decl_itr);
  }
  return modified;
}

uint32_t DebugInfoManager::GetParentScope(uint32_t child_scope) {
  auto dbg_scope_itr = id_to_dbg_inst_.find(child_scope);
  assert(dbg_scope_itr != id_to_dbg_inst_.end());
  CommonDebugInfoInstructions debug_opcode =
      dbg_scope_itr->second->GetCommonDebugOpcode();
  uint32_t parent_scope = kNoDebugScope;
  switch (debug_opcode) {
    case CommonDebugInfoDebugFunction:
      parent_scope = dbg_scope_itr->second->GetSingleWordOperand(
          kDebugFunctionOperandParentIndex);
      break;
    case CommonDebugInfoDebugLexicalBlock:
      parent_scope = dbg_scope_itr->second->GetSingleWordOperand(
          kDebugLexicalBlockOperandParentIndex);
      break;
    case CommonDebugInfoDebugTypeComposite:
      parent_scope = dbg_scope_itr->second->GetSingleWordOperand(
          kDebugTypeCompositeOperandParentIndex);
      break;
    case CommonDebugInfoDebugCompilationUnit:
      // DebugCompilationUnit does not have a parent scope.
      break;
    default:
      assert(false &&
             "Unreachable. A debug scope instruction must be "
             "DebugFunction, DebugTypeComposite, DebugLexicalBlock, "
             "or DebugCompilationUnit.");
      break;
  }
  return parent_scope;
}

bool DebugInfoManager::IsAncestorOfScope(uint32_t scope, uint32_t ancestor) {
  uint32_t ancestor_scope_itr = scope;
  while (ancestor_scope_itr != kNoDebugScope) {
    if (ancestor == ancestor_scope_itr) return true;
    ancestor_scope_itr = GetParentScope(ancestor_scope_itr);
  }
  return false;
}

bool DebugInfoManager::IsDeclareVisibleToInstr(Instruction* dbg_declare,
                                               Instruction* scope) {
  assert(dbg_declare != nullptr);
  assert(scope != nullptr);

  std::vector<uint32_t> scope_ids;
  if (scope->opcode() == SpvOpPhi) {
    scope_ids.push_back(scope->GetDebugScope().GetLexicalScope());
    for (uint32_t i = 0; i < scope->NumInOperands(); i += 2) {
      auto* value = context()->get_def_use_mgr()->GetDef(
          scope->GetSingleWordInOperand(i));
      if (value != nullptr)
        scope_ids.push_back(value->GetDebugScope().GetLexicalScope());
    }
  } else {
    scope_ids.push_back(scope->GetDebugScope().GetLexicalScope());
  }

  uint32_t dbg_local_var_id =
      dbg_declare->GetSingleWordOperand(kDebugDeclareOperandLocalVariableIndex);
  auto dbg_local_var_itr = id_to_dbg_inst_.find(dbg_local_var_id);
  assert(dbg_local_var_itr != id_to_dbg_inst_.end());
  uint32_t decl_scope_id = dbg_local_var_itr->second->GetSingleWordOperand(
      kDebugLocalVariableOperandParentIndex);

  // If the scope of DebugDeclare is an ancestor scope of the instruction's
  // scope, the local variable is visible to the instruction.
  for (uint32_t scope_id : scope_ids) {
    if (scope_id != kNoDebugScope &&
        IsAncestorOfScope(scope_id, decl_scope_id)) {
      return true;
    }
  }
  return false;
}

bool DebugInfoManager::AddDebugValueIfVarDeclIsVisible(
    Instruction* scope_and_line, uint32_t variable_id, uint32_t value_id,
    Instruction* insert_pos, std::unordered_set<Instruction*>* invisible_decls,
    bool force) {
  assert(scope_and_line != nullptr);

  auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id);
  if (dbg_decl_itr == var_id_to_dbg_decl_.end()) return false;

  bool modified = false;
  for (auto* dbg_decl_or_val : dbg_decl_itr->second) {
    if (!IsDeclareVisibleToInstr(dbg_decl_or_val, scope_and_line) && !force) {
      if (invisible_decls) invisible_decls->insert(dbg_decl_or_val);
      continue;
    }

    // Avoid inserting the new DebugValue between OpPhi or OpVariable
    // instructions.
    Instruction* insert_before = insert_pos->NextNode();
    while (insert_before->opcode() == SpvOpPhi ||
           insert_before->opcode() == SpvOpVariable) {
      insert_before = insert_before->NextNode();
    }
    modified |= AddDebugValueForDecl(dbg_decl_or_val, value_id, insert_before,
                                     scope_and_line) != nullptr;
  }
  return modified;
}

Instruction* DebugInfoManager::AddDebugValueForDecl(
    Instruction* dbg_decl, uint32_t value_id, Instruction* insert_before,
    Instruction* scope_and_line) {
  if (dbg_decl == nullptr || !IsDebugDeclare(dbg_decl)) return nullptr;

  std::unique_ptr<Instruction> dbg_val(dbg_decl->Clone(context()));
  dbg_val->SetResultId(context()->TakeNextId());
  dbg_val->SetInOperand(kExtInstInstructionInIdx, {CommonDebugInfoDebugValue});
  dbg_val->SetOperand(kDebugDeclareOperandVariableIndex, {value_id});
  dbg_val->SetOperand(kDebugValueOperandExpressionIndex,
                      {GetEmptyDebugExpression()->result_id()});
  dbg_val->UpdateDebugInfoFrom(scope_and_line);

  auto* added_dbg_val = insert_before->InsertBefore(std::move(dbg_val));
  AnalyzeDebugInst(added_dbg_val);
  if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
    context()->get_def_use_mgr()->AnalyzeInstDefUse(added_dbg_val);
  if (context()->AreAnalysesValid(
          IRContext::Analysis::kAnalysisInstrToBlockMapping)) {
    auto insert_blk = context()->get_instr_block(insert_before);
    context()->set_instr_block(added_dbg_val, insert_blk);
  }
  return added_dbg_val;
}

uint32_t DebugInfoManager::GetVulkanDebugOperation(Instruction* inst) {
  assert(inst->GetShader100DebugOpcode() ==
             NonSemanticShaderDebugInfo100DebugOperation &&
         "inst must be Vulkan DebugOperation");
  return context()
      ->get_constant_mgr()
      ->GetConstantFromInst(context()->get_def_use_mgr()->GetDef(
          inst->GetSingleWordOperand(kDebugOperationOperandOperationIndex)))
      ->GetU32();
}

uint32_t DebugInfoManager::GetVariableIdOfDebugValueUsedForDeclare(
    Instruction* inst) {
  if (inst->GetCommonDebugOpcode() != CommonDebugInfoDebugValue) return 0;

  auto* expr =
      GetDbgInst(inst->GetSingleWordOperand(kDebugValueOperandExpressionIndex));
  if (expr == nullptr) return 0;
  if (expr->NumOperands() != kDebugExpressOperandOperationIndex + 1) return 0;

  auto* operation = GetDbgInst(
      expr->GetSingleWordOperand(kDebugExpressOperandOperationIndex));
  if (operation == nullptr) return 0;

  // OpenCL.DebugInfo.100 contains a literal for the operation, Vulkan uses an
  // OpConstant.
  if (inst->IsOpenCL100DebugInstr()) {
    if (operation->GetSingleWordOperand(kDebugOperationOperandOperationIndex) !=
        OpenCLDebugInfo100Deref) {
      return 0;
    }
  } else {
    uint32_t operation_const = GetVulkanDebugOperation(operation);
    if (operation_const != NonSemanticShaderDebugInfo100Deref) {
      return 0;
    }
  }

  uint32_t var_id =
      inst->GetSingleWordOperand(kDebugDeclareOperandVariableIndex);
  if (!context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse)) {
    assert(false &&
           "Checking a DebugValue can be used for declare needs DefUseManager");
    return 0;
  }

  auto* var = context()->get_def_use_mgr()->GetDef(var_id);
  if (var->opcode() == SpvOpVariable &&
      SpvStorageClass(var->GetSingleWordOperand(
          kOpVariableOperandStorageClassIndex)) == SpvStorageClassFunction) {
    return var_id;
  }
  return 0;
}

bool DebugInfoManager::IsDebugDeclare(Instruction* instr) {
  if (!instr->IsCommonDebugInstr()) return false;
  return instr->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare ||
         GetVariableIdOfDebugValueUsedForDeclare(instr) != 0;
}

void DebugInfoManager::ReplaceAllUsesInDebugScopeWithPredicate(
    uint32_t before, uint32_t after,
    const std::function<bool(Instruction*)>& predicate) {
  auto scope_id_to_users_itr = scope_id_to_users_.find(before);
  if (scope_id_to_users_itr != scope_id_to_users_.end()) {
    for (Instruction* inst : scope_id_to_users_itr->second) {
      if (predicate(inst)) inst->UpdateLexicalScope(after);
    }
    scope_id_to_users_[after] = scope_id_to_users_itr->second;
    scope_id_to_users_.erase(scope_id_to_users_itr);
  }
  auto inlinedat_id_to_users_itr = inlinedat_id_to_users_.find(before);
  if (inlinedat_id_to_users_itr != inlinedat_id_to_users_.end()) {
    for (Instruction* inst : inlinedat_id_to_users_itr->second) {
      if (predicate(inst)) inst->UpdateDebugInlinedAt(after);
    }
    inlinedat_id_to_users_[after] = inlinedat_id_to_users_itr->second;
    inlinedat_id_to_users_.erase(inlinedat_id_to_users_itr);
  }
}

void DebugInfoManager::ClearDebugScopeAndInlinedAtUses(Instruction* inst) {
  auto scope_id_to_users_itr = scope_id_to_users_.find(inst->result_id());
  if (scope_id_to_users_itr != scope_id_to_users_.end()) {
    scope_id_to_users_.erase(scope_id_to_users_itr);
  }
  auto inlinedat_id_to_users_itr =
      inlinedat_id_to_users_.find(inst->result_id());
  if (inlinedat_id_to_users_itr != inlinedat_id_to_users_.end()) {
    inlinedat_id_to_users_.erase(inlinedat_id_to_users_itr);
  }
}

void DebugInfoManager::AnalyzeDebugInst(Instruction* inst) {
  if (inst->GetDebugScope().GetLexicalScope() != kNoDebugScope) {
    auto& users = scope_id_to_users_[inst->GetDebugScope().GetLexicalScope()];
    users.insert(inst);
  }
  if (inst->GetDebugInlinedAt() != kNoInlinedAt) {
    auto& users = inlinedat_id_to_users_[inst->GetDebugInlinedAt()];
    users.insert(inst);
  }

  if (!inst->IsCommonDebugInstr()) return;

  RegisterDbgInst(inst);

  if (inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugFunction ||
      inst->GetShader100DebugOpcode() ==
          NonSemanticShaderDebugInfo100DebugFunctionDefinition) {
    RegisterDbgFunction(inst);
  }

  if (deref_operation_ == nullptr &&
      inst->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugOperation &&
      inst->GetSingleWordOperand(kDebugOperationOperandOperationIndex) ==
          OpenCLDebugInfo100Deref) {
    deref_operation_ = inst;
  }

  if (deref_operation_ == nullptr &&
      inst->GetShader100DebugOpcode() ==
          NonSemanticShaderDebugInfo100DebugOperation) {
    uint32_t operation_const = GetVulkanDebugOperation(inst);
    if (operation_const == NonSemanticShaderDebugInfo100Deref) {
      deref_operation_ = inst;
    }
  }

  if (debug_info_none_inst_ == nullptr &&
      inst->GetCommonDebugOpcode() == CommonDebugInfoDebugInfoNone) {
    debug_info_none_inst_ = inst;
  }

  if (empty_debug_expr_inst_ == nullptr && IsEmptyDebugExpression(inst)) {
    empty_debug_expr_inst_ = inst;
  }

  if (inst->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare) {
    uint32_t var_id =
        inst->GetSingleWordOperand(kDebugDeclareOperandVariableIndex);
    RegisterDbgDeclare(var_id, inst);
  }

  if (uint32_t var_id = GetVariableIdOfDebugValueUsedForDeclare(inst)) {
    RegisterDbgDeclare(var_id, inst);
  }
}

void DebugInfoManager::ConvertDebugGlobalToLocalVariable(
    Instruction* dbg_global_var, Instruction* local_var) {
  if (dbg_global_var->GetCommonDebugOpcode() !=
      CommonDebugInfoDebugGlobalVariable) {
    return;
  }
  assert(local_var->opcode() == SpvOpVariable ||
         local_var->opcode() == SpvOpFunctionParameter);

  // Convert |dbg_global_var| to DebugLocalVariable
  dbg_global_var->SetInOperand(kExtInstInstructionInIdx,
                               {CommonDebugInfoDebugLocalVariable});
  auto flags = dbg_global_var->GetSingleWordOperand(
      kDebugGlobalVariableOperandFlagsIndex);
  for (uint32_t i = dbg_global_var->NumInOperands() - 1;
       i >= kDebugLocalVariableOperandFlagsIndex; --i) {
    dbg_global_var->RemoveOperand(i);
  }
  dbg_global_var->SetOperand(kDebugLocalVariableOperandFlagsIndex, {flags});
  context()->ForgetUses(dbg_global_var);
  context()->AnalyzeUses(dbg_global_var);

  // Create a DebugDeclare
  std::unique_ptr<Instruction> new_dbg_decl(new Instruction(
      context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
      context()->TakeNextId(),
      {
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
           {static_cast<uint32_t>(CommonDebugInfoDebugDeclare)}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
           {dbg_global_var->result_id()}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {local_var->result_id()}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
           {GetEmptyDebugExpression()->result_id()}},
      }));
  // Must insert after all OpVariables in block
  Instruction* insert_before = local_var;
  while (insert_before->opcode() == SpvOpVariable)
    insert_before = insert_before->NextNode();
  auto* added_dbg_decl = insert_before->InsertBefore(std::move(new_dbg_decl));
  if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
    context()->get_def_use_mgr()->AnalyzeInstDefUse(added_dbg_decl);
  if (context()->AreAnalysesValid(
          IRContext::Analysis::kAnalysisInstrToBlockMapping)) {
    auto insert_blk = context()->get_instr_block(local_var);
    context()->set_instr_block(added_dbg_decl, insert_blk);
  }
}

void DebugInfoManager::AnalyzeDebugInsts(Module& module) {
  deref_operation_ = nullptr;
  debug_info_none_inst_ = nullptr;
  empty_debug_expr_inst_ = nullptr;
  module.ForEachInst([this](Instruction* cpi) { AnalyzeDebugInst(cpi); });

  // Move |empty_debug_expr_inst_| to the beginning of the debug instruction
  // list.
  if (empty_debug_expr_inst_ != nullptr &&
      empty_debug_expr_inst_->PreviousNode() != nullptr &&
      empty_debug_expr_inst_->PreviousNode()->IsCommonDebugInstr()) {
    empty_debug_expr_inst_->InsertBefore(
        &*context()->module()->ext_inst_debuginfo_begin());
  }

  // Move |debug_info_none_inst_| to the beginning of the debug instruction
  // list.
  if (debug_info_none_inst_ != nullptr &&
      debug_info_none_inst_->PreviousNode() != nullptr &&
      debug_info_none_inst_->PreviousNode()->IsCommonDebugInstr()) {
    debug_info_none_inst_->InsertBefore(
        &*context()->module()->ext_inst_debuginfo_begin());
  }
}

void DebugInfoManager::ClearDebugInfo(Instruction* instr) {
  auto scope_id_to_users_itr =
      scope_id_to_users_.find(instr->GetDebugScope().GetLexicalScope());
  if (scope_id_to_users_itr != scope_id_to_users_.end()) {
    scope_id_to_users_itr->second.erase(instr);
  }
  auto inlinedat_id_to_users_itr =
      inlinedat_id_to_users_.find(instr->GetDebugInlinedAt());
  if (inlinedat_id_to_users_itr != inlinedat_id_to_users_.end()) {
    inlinedat_id_to_users_itr->second.erase(instr);
  }

  if (instr == nullptr || !instr->IsCommonDebugInstr()) {
    return;
  }

  id_to_dbg_inst_.erase(instr->result_id());

  if (instr->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugFunction) {
    auto fn_id =
        instr->GetSingleWordOperand(kDebugFunctionOperandFunctionIndex);
    fn_id_to_dbg_fn_.erase(fn_id);
  }
  if (instr->GetShader100DebugOpcode() ==
      NonSemanticShaderDebugInfo100DebugFunctionDefinition) {
    auto fn_id = instr->GetSingleWordOperand(
        kDebugFunctionDefinitionOperandOpFunctionIndex);
    fn_id_to_dbg_fn_.erase(fn_id);
  }

  if (instr->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare ||
      instr->GetCommonDebugOpcode() == CommonDebugInfoDebugValue) {
    auto var_or_value_id =
        instr->GetSingleWordOperand(kDebugDeclareOperandVariableIndex);
    auto dbg_decl_itr = var_id_to_dbg_decl_.find(var_or_value_id);
    if (dbg_decl_itr != var_id_to_dbg_decl_.end()) {
      dbg_decl_itr->second.erase(instr);
    }
  }

  if (deref_operation_ == instr) {
    deref_operation_ = nullptr;
    for (auto dbg_instr_itr = context()->module()->ext_inst_debuginfo_begin();
         dbg_instr_itr != context()->module()->ext_inst_debuginfo_end();
         ++dbg_instr_itr) {
      // OpenCL.DebugInfo.100 contains the operation as a literal operand, in
      // Vulkan it's referenced as an OpConstant.
      if (instr != &*dbg_instr_itr &&
          dbg_instr_itr->GetOpenCL100DebugOpcode() ==
              OpenCLDebugInfo100DebugOperation &&
          dbg_instr_itr->GetSingleWordOperand(
              kDebugOperationOperandOperationIndex) ==
              OpenCLDebugInfo100Deref) {
        deref_operation_ = &*dbg_instr_itr;
        break;
      } else if (instr != &*dbg_instr_itr &&
                 dbg_instr_itr->GetShader100DebugOpcode() ==
                     NonSemanticShaderDebugInfo100DebugOperation) {
        uint32_t operation_const = GetVulkanDebugOperation(&*dbg_instr_itr);
        if (operation_const == NonSemanticShaderDebugInfo100Deref) {
          deref_operation_ = &*dbg_instr_itr;
          break;
        }
      }
    }
  }

  if (debug_info_none_inst_ == instr) {
    debug_info_none_inst_ = nullptr;
    for (auto dbg_instr_itr = context()->module()->ext_inst_debuginfo_begin();
         dbg_instr_itr != context()->module()->ext_inst_debuginfo_end();
         ++dbg_instr_itr) {
      if (instr != &*dbg_instr_itr && dbg_instr_itr->GetCommonDebugOpcode() ==
                                          CommonDebugInfoDebugInfoNone) {
        debug_info_none_inst_ = &*dbg_instr_itr;
        break;
      }
    }
  }

  if (empty_debug_expr_inst_ == instr) {
    empty_debug_expr_inst_ = nullptr;
    for (auto dbg_instr_itr = context()->module()->ext_inst_debuginfo_begin();
         dbg_instr_itr != context()->module()->ext_inst_debuginfo_end();
         ++dbg_instr_itr) {
      if (instr != &*dbg_instr_itr && IsEmptyDebugExpression(&*dbg_instr_itr)) {
        empty_debug_expr_inst_ = &*dbg_instr_itr;
        break;
      }
    }
  }
}

}  // namespace analysis
}  // namespace opt
}  // namespace spvtools
