//===-- SBBlock.cpp -------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/API/SBBlock.h"
#include "SBReproducerPrivate.h"
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBValue.h"
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"

using namespace lldb;
using namespace lldb_private;

SBBlock::SBBlock() : m_opaque_ptr(nullptr) {
  LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBBlock);
}

SBBlock::SBBlock(lldb_private::Block *lldb_object_ptr)
    : m_opaque_ptr(lldb_object_ptr) {}

SBBlock::SBBlock(const SBBlock &rhs) : m_opaque_ptr(rhs.m_opaque_ptr) {
  LLDB_RECORD_CONSTRUCTOR(SBBlock, (const lldb::SBBlock &), rhs);
}

const SBBlock &SBBlock::operator=(const SBBlock &rhs) {
  LLDB_RECORD_METHOD(const lldb::SBBlock &,
                     SBBlock, operator=,(const lldb::SBBlock &), rhs);

  m_opaque_ptr = rhs.m_opaque_ptr;
  return LLDB_RECORD_RESULT(*this);
}

SBBlock::~SBBlock() { m_opaque_ptr = nullptr; }

bool SBBlock::IsValid() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBlock, IsValid);
  return this->operator bool();
}
SBBlock::operator bool() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBlock, operator bool);

  return m_opaque_ptr != nullptr;
}

bool SBBlock::IsInlined() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBlock, IsInlined);

  if (m_opaque_ptr)
    return m_opaque_ptr->GetInlinedFunctionInfo() != nullptr;
  return false;
}

const char *SBBlock::GetInlinedName() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBBlock, GetInlinedName);

  if (m_opaque_ptr) {
    const InlineFunctionInfo *inlined_info =
        m_opaque_ptr->GetInlinedFunctionInfo();
    if (inlined_info) {
      return inlined_info->GetName().AsCString(nullptr);
    }
  }
  return nullptr;
}

SBFileSpec SBBlock::GetInlinedCallSiteFile() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBFileSpec, SBBlock,
                                   GetInlinedCallSiteFile);

  SBFileSpec sb_file;
  if (m_opaque_ptr) {
    const InlineFunctionInfo *inlined_info =
        m_opaque_ptr->GetInlinedFunctionInfo();
    if (inlined_info)
      sb_file.SetFileSpec(inlined_info->GetCallSite().GetFile());
  }
  return LLDB_RECORD_RESULT(sb_file);
}

uint32_t SBBlock::GetInlinedCallSiteLine() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(uint32_t, SBBlock, GetInlinedCallSiteLine);

  if (m_opaque_ptr) {
    const InlineFunctionInfo *inlined_info =
        m_opaque_ptr->GetInlinedFunctionInfo();
    if (inlined_info)
      return inlined_info->GetCallSite().GetLine();
  }
  return 0;
}

uint32_t SBBlock::GetInlinedCallSiteColumn() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(uint32_t, SBBlock, GetInlinedCallSiteColumn);

  if (m_opaque_ptr) {
    const InlineFunctionInfo *inlined_info =
        m_opaque_ptr->GetInlinedFunctionInfo();
    if (inlined_info)
      return inlined_info->GetCallSite().GetColumn();
  }
  return 0;
}

void SBBlock::AppendVariables(bool can_create, bool get_parent_variables,
                              lldb_private::VariableList *var_list) {
  if (IsValid()) {
    bool show_inline = true;
    m_opaque_ptr->AppendVariables(can_create, get_parent_variables, show_inline,
                                  [](Variable *) { return true; }, var_list);
  }
}

SBBlock SBBlock::GetParent() {
  LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBlock, SBBlock, GetParent);

  SBBlock sb_block;
  if (m_opaque_ptr)
    sb_block.m_opaque_ptr = m_opaque_ptr->GetParent();
  return LLDB_RECORD_RESULT(sb_block);
}

lldb::SBBlock SBBlock::GetContainingInlinedBlock() {
  LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBlock, SBBlock, GetContainingInlinedBlock);

  SBBlock sb_block;
  if (m_opaque_ptr)
    sb_block.m_opaque_ptr = m_opaque_ptr->GetContainingInlinedBlock();
  return LLDB_RECORD_RESULT(sb_block);
}

SBBlock SBBlock::GetSibling() {
  LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBlock, SBBlock, GetSibling);

  SBBlock sb_block;
  if (m_opaque_ptr)
    sb_block.m_opaque_ptr = m_opaque_ptr->GetSibling();
  return LLDB_RECORD_RESULT(sb_block);
}

SBBlock SBBlock::GetFirstChild() {
  LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBlock, SBBlock, GetFirstChild);

  SBBlock sb_block;
  if (m_opaque_ptr)
    sb_block.m_opaque_ptr = m_opaque_ptr->GetFirstChild();
  return LLDB_RECORD_RESULT(sb_block);
}

lldb_private::Block *SBBlock::GetPtr() { return m_opaque_ptr; }

void SBBlock::SetPtr(lldb_private::Block *block) { m_opaque_ptr = block; }

bool SBBlock::GetDescription(SBStream &description) {
  LLDB_RECORD_METHOD(bool, SBBlock, GetDescription, (lldb::SBStream &),
                     description);

  Stream &strm = description.ref();

  if (m_opaque_ptr) {
    lldb::user_id_t id = m_opaque_ptr->GetID();
    strm.Printf("Block: {id: %" PRIu64 "} ", id);
    if (IsInlined()) {
      strm.Printf(" (inlined, '%s') ", GetInlinedName());
    }
    lldb_private::SymbolContext sc;
    m_opaque_ptr->CalculateSymbolContext(&sc);
    if (sc.function) {
      m_opaque_ptr->DumpAddressRanges(
          &strm,
          sc.function->GetAddressRange().GetBaseAddress().GetFileAddress());
    }
  } else
    strm.PutCString("No value");

  return true;
}

uint32_t SBBlock::GetNumRanges() {
  LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBBlock, GetNumRanges);

  if (m_opaque_ptr)
    return m_opaque_ptr->GetNumRanges();
  return 0;
}

lldb::SBAddress SBBlock::GetRangeStartAddress(uint32_t idx) {
  LLDB_RECORD_METHOD(lldb::SBAddress, SBBlock, GetRangeStartAddress, (uint32_t),
                     idx);

  lldb::SBAddress sb_addr;
  if (m_opaque_ptr) {
    AddressRange range;
    if (m_opaque_ptr->GetRangeAtIndex(idx, range)) {
      sb_addr.ref() = range.GetBaseAddress();
    }
  }
  return LLDB_RECORD_RESULT(sb_addr);
}

lldb::SBAddress SBBlock::GetRangeEndAddress(uint32_t idx) {
  LLDB_RECORD_METHOD(lldb::SBAddress, SBBlock, GetRangeEndAddress, (uint32_t),
                     idx);

  lldb::SBAddress sb_addr;
  if (m_opaque_ptr) {
    AddressRange range;
    if (m_opaque_ptr->GetRangeAtIndex(idx, range)) {
      sb_addr.ref() = range.GetBaseAddress();
      sb_addr.ref().Slide(range.GetByteSize());
    }
  }
  return LLDB_RECORD_RESULT(sb_addr);
}

uint32_t SBBlock::GetRangeIndexForBlockAddress(lldb::SBAddress block_addr) {
  LLDB_RECORD_METHOD(uint32_t, SBBlock, GetRangeIndexForBlockAddress,
                     (lldb::SBAddress), block_addr);

  if (m_opaque_ptr && block_addr.IsValid()) {
    return m_opaque_ptr->GetRangeIndexContainingAddress(block_addr.ref());
  }

  return UINT32_MAX;
}

lldb::SBValueList SBBlock::GetVariables(lldb::SBFrame &frame, bool arguments,
                                        bool locals, bool statics,
                                        lldb::DynamicValueType use_dynamic) {
  LLDB_RECORD_METHOD(
      lldb::SBValueList, SBBlock, GetVariables,
      (lldb::SBFrame &, bool, bool, bool, lldb::DynamicValueType), frame,
      arguments, locals, statics, use_dynamic);

  Block *block = GetPtr();
  SBValueList value_list;
  if (block) {
    StackFrameSP frame_sp(frame.GetFrameSP());
    VariableListSP variable_list_sp(block->GetBlockVariableList(true));

    if (variable_list_sp) {
      const size_t num_variables = variable_list_sp->GetSize();
      if (num_variables) {
        for (size_t i = 0; i < num_variables; ++i) {
          VariableSP variable_sp(variable_list_sp->GetVariableAtIndex(i));
          if (variable_sp) {
            bool add_variable = false;
            switch (variable_sp->GetScope()) {
            case eValueTypeVariableGlobal:
            case eValueTypeVariableStatic:
            case eValueTypeVariableThreadLocal:
              add_variable = statics;
              break;

            case eValueTypeVariableArgument:
              add_variable = arguments;
              break;

            case eValueTypeVariableLocal:
              add_variable = locals;
              break;

            default:
              break;
            }
            if (add_variable) {
              if (frame_sp) {
                lldb::ValueObjectSP valobj_sp(
                    frame_sp->GetValueObjectForFrameVariable(variable_sp,
                                                             eNoDynamicValues));
                SBValue value_sb;
                value_sb.SetSP(valobj_sp, use_dynamic);
                value_list.Append(value_sb);
              }
            }
          }
        }
      }
    }
  }
  return LLDB_RECORD_RESULT(value_list);
}

lldb::SBValueList SBBlock::GetVariables(lldb::SBTarget &target, bool arguments,
                                        bool locals, bool statics) {
  LLDB_RECORD_METHOD(lldb::SBValueList, SBBlock, GetVariables,
                     (lldb::SBTarget &, bool, bool, bool), target, arguments,
                     locals, statics);

  Block *block = GetPtr();

  SBValueList value_list;
  if (block) {
    TargetSP target_sp(target.GetSP());

    VariableListSP variable_list_sp(block->GetBlockVariableList(true));

    if (variable_list_sp) {
      const size_t num_variables = variable_list_sp->GetSize();
      if (num_variables) {
        for (size_t i = 0; i < num_variables; ++i) {
          VariableSP variable_sp(variable_list_sp->GetVariableAtIndex(i));
          if (variable_sp) {
            bool add_variable = false;
            switch (variable_sp->GetScope()) {
            case eValueTypeVariableGlobal:
            case eValueTypeVariableStatic:
            case eValueTypeVariableThreadLocal:
              add_variable = statics;
              break;

            case eValueTypeVariableArgument:
              add_variable = arguments;
              break;

            case eValueTypeVariableLocal:
              add_variable = locals;
              break;

            default:
              break;
            }
            if (add_variable) {
              if (target_sp)
                value_list.Append(
                    ValueObjectVariable::Create(target_sp.get(), variable_sp));
            }
          }
        }
      }
    }
  }
  return LLDB_RECORD_RESULT(value_list);
}

namespace lldb_private {
namespace repro {

template <>
void RegisterMethods<SBBlock>(Registry &R) {
  LLDB_REGISTER_CONSTRUCTOR(SBBlock, ());
  LLDB_REGISTER_CONSTRUCTOR(SBBlock, (const lldb::SBBlock &));
  LLDB_REGISTER_METHOD(const lldb::SBBlock &,
                       SBBlock, operator=,(const lldb::SBBlock &));
  LLDB_REGISTER_METHOD_CONST(bool, SBBlock, IsValid, ());
  LLDB_REGISTER_METHOD_CONST(bool, SBBlock, operator bool, ());
  LLDB_REGISTER_METHOD_CONST(bool, SBBlock, IsInlined, ());
  LLDB_REGISTER_METHOD_CONST(const char *, SBBlock, GetInlinedName, ());
  LLDB_REGISTER_METHOD_CONST(lldb::SBFileSpec, SBBlock,
                             GetInlinedCallSiteFile, ());
  LLDB_REGISTER_METHOD_CONST(uint32_t, SBBlock, GetInlinedCallSiteLine, ());
  LLDB_REGISTER_METHOD_CONST(uint32_t, SBBlock, GetInlinedCallSiteColumn, ());
  LLDB_REGISTER_METHOD(lldb::SBBlock, SBBlock, GetParent, ());
  LLDB_REGISTER_METHOD(lldb::SBBlock, SBBlock, GetContainingInlinedBlock, ());
  LLDB_REGISTER_METHOD(lldb::SBBlock, SBBlock, GetSibling, ());
  LLDB_REGISTER_METHOD(lldb::SBBlock, SBBlock, GetFirstChild, ());
  LLDB_REGISTER_METHOD(bool, SBBlock, GetDescription, (lldb::SBStream &));
  LLDB_REGISTER_METHOD(uint32_t, SBBlock, GetNumRanges, ());
  LLDB_REGISTER_METHOD(lldb::SBAddress, SBBlock, GetRangeStartAddress,
                       (uint32_t));
  LLDB_REGISTER_METHOD(lldb::SBAddress, SBBlock, GetRangeEndAddress,
                       (uint32_t));
  LLDB_REGISTER_METHOD(uint32_t, SBBlock, GetRangeIndexForBlockAddress,
                       (lldb::SBAddress));
  LLDB_REGISTER_METHOD(
      lldb::SBValueList, SBBlock, GetVariables,
      (lldb::SBFrame &, bool, bool, bool, lldb::DynamicValueType));
  LLDB_REGISTER_METHOD(lldb::SBValueList, SBBlock, GetVariables,
                       (lldb::SBTarget &, bool, bool, bool));
}

}
}
