//===-- SBSymbol.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/SBSymbol.h"
#include "SBReproducerPrivate.h"
#include "lldb/API/SBStream.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Target.h"

using namespace lldb;
using namespace lldb_private;

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

SBSymbol::SBSymbol(lldb_private::Symbol *lldb_object_ptr)
    : m_opaque_ptr(lldb_object_ptr) {}

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

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

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

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

void SBSymbol::SetSymbol(lldb_private::Symbol *lldb_object_ptr) {
  m_opaque_ptr = lldb_object_ptr;
}

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

  return m_opaque_ptr != nullptr;
}

const char *SBSymbol::GetName() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBSymbol, GetName);

  const char *name = nullptr;
  if (m_opaque_ptr)
    name = m_opaque_ptr->GetName().AsCString();

  return name;
}

const char *SBSymbol::GetDisplayName() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBSymbol, GetDisplayName);

  const char *name = nullptr;
  if (m_opaque_ptr)
    name = m_opaque_ptr->GetMangled().GetDisplayDemangledName().AsCString();

  return name;
}

const char *SBSymbol::GetMangledName() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBSymbol, GetMangledName);

  const char *name = nullptr;
  if (m_opaque_ptr)
    name = m_opaque_ptr->GetMangled().GetMangledName().AsCString();
  return name;
}

bool SBSymbol::operator==(const SBSymbol &rhs) const {
  LLDB_RECORD_METHOD_CONST(bool, SBSymbol, operator==,(const lldb::SBSymbol &),
                           rhs);

  return m_opaque_ptr == rhs.m_opaque_ptr;
}

bool SBSymbol::operator!=(const SBSymbol &rhs) const {
  LLDB_RECORD_METHOD_CONST(bool, SBSymbol, operator!=,(const lldb::SBSymbol &),
                           rhs);

  return m_opaque_ptr != rhs.m_opaque_ptr;
}

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

  Stream &strm = description.ref();

  if (m_opaque_ptr) {
    m_opaque_ptr->GetDescription(&strm, lldb::eDescriptionLevelFull, nullptr);
  } else
    strm.PutCString("No value");

  return true;
}

SBInstructionList SBSymbol::GetInstructions(SBTarget target) {
  LLDB_RECORD_METHOD(lldb::SBInstructionList, SBSymbol, GetInstructions,
                     (lldb::SBTarget), target);

  return LLDB_RECORD_RESULT(GetInstructions(target, nullptr));
}

SBInstructionList SBSymbol::GetInstructions(SBTarget target,
                                            const char *flavor_string) {
  LLDB_RECORD_METHOD(lldb::SBInstructionList, SBSymbol, GetInstructions,
                     (lldb::SBTarget, const char *), target, flavor_string);

  SBInstructionList sb_instructions;
  if (m_opaque_ptr) {
    TargetSP target_sp(target.GetSP());
    std::unique_lock<std::recursive_mutex> lock;
    if (target_sp && m_opaque_ptr->ValueIsAddress()) {
      lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
      const Address &symbol_addr = m_opaque_ptr->GetAddressRef();
      ModuleSP module_sp = symbol_addr.GetModule();
      if (module_sp) {
        AddressRange symbol_range(symbol_addr, m_opaque_ptr->GetByteSize());
        const bool force_live_memory = true;
        sb_instructions.SetDisassembler(Disassembler::DisassembleRange(
            module_sp->GetArchitecture(), nullptr, flavor_string, *target_sp,
            symbol_range, force_live_memory));
      }
    }
  }
  return LLDB_RECORD_RESULT(sb_instructions);
}

lldb_private::Symbol *SBSymbol::get() { return m_opaque_ptr; }

void SBSymbol::reset(lldb_private::Symbol *symbol) { m_opaque_ptr = symbol; }

SBAddress SBSymbol::GetStartAddress() {
  LLDB_RECORD_METHOD_NO_ARGS(lldb::SBAddress, SBSymbol, GetStartAddress);

  SBAddress addr;
  if (m_opaque_ptr && m_opaque_ptr->ValueIsAddress()) {
    addr.SetAddress(m_opaque_ptr->GetAddressRef());
  }
  return LLDB_RECORD_RESULT(addr);
}

SBAddress SBSymbol::GetEndAddress() {
  LLDB_RECORD_METHOD_NO_ARGS(lldb::SBAddress, SBSymbol, GetEndAddress);

  SBAddress addr;
  if (m_opaque_ptr && m_opaque_ptr->ValueIsAddress()) {
    lldb::addr_t range_size = m_opaque_ptr->GetByteSize();
    if (range_size > 0) {
      addr.SetAddress(m_opaque_ptr->GetAddressRef());
      addr->Slide(m_opaque_ptr->GetByteSize());
    }
  }
  return LLDB_RECORD_RESULT(addr);
}

uint32_t SBSymbol::GetPrologueByteSize() {
  LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBSymbol, GetPrologueByteSize);

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

SymbolType SBSymbol::GetType() {
  LLDB_RECORD_METHOD_NO_ARGS(lldb::SymbolType, SBSymbol, GetType);

  if (m_opaque_ptr)
    return m_opaque_ptr->GetType();
  return eSymbolTypeInvalid;
}

bool SBSymbol::IsExternal() {
  LLDB_RECORD_METHOD_NO_ARGS(bool, SBSymbol, IsExternal);

  if (m_opaque_ptr)
    return m_opaque_ptr->IsExternal();
  return false;
}

bool SBSymbol::IsSynthetic() {
  LLDB_RECORD_METHOD_NO_ARGS(bool, SBSymbol, IsSynthetic);

  if (m_opaque_ptr)
    return m_opaque_ptr->IsSynthetic();
  return false;
}

namespace lldb_private {
namespace repro {

template <>
void RegisterMethods<SBSymbol>(Registry &R) {
  LLDB_REGISTER_CONSTRUCTOR(SBSymbol, ());
  LLDB_REGISTER_CONSTRUCTOR(SBSymbol, (const lldb::SBSymbol &));
  LLDB_REGISTER_METHOD(const lldb::SBSymbol &,
                       SBSymbol, operator=,(const lldb::SBSymbol &));
  LLDB_REGISTER_METHOD_CONST(bool, SBSymbol, IsValid, ());
  LLDB_REGISTER_METHOD_CONST(bool, SBSymbol, operator bool, ());
  LLDB_REGISTER_METHOD_CONST(const char *, SBSymbol, GetName, ());
  LLDB_REGISTER_METHOD_CONST(const char *, SBSymbol, GetDisplayName, ());
  LLDB_REGISTER_METHOD_CONST(const char *, SBSymbol, GetMangledName, ());
  LLDB_REGISTER_METHOD_CONST(bool,
                             SBSymbol, operator==,(const lldb::SBSymbol &));
  LLDB_REGISTER_METHOD_CONST(bool,
                             SBSymbol, operator!=,(const lldb::SBSymbol &));
  LLDB_REGISTER_METHOD(bool, SBSymbol, GetDescription, (lldb::SBStream &));
  LLDB_REGISTER_METHOD(lldb::SBInstructionList, SBSymbol, GetInstructions,
                       (lldb::SBTarget));
  LLDB_REGISTER_METHOD(lldb::SBInstructionList, SBSymbol, GetInstructions,
                       (lldb::SBTarget, const char *));
  LLDB_REGISTER_METHOD(lldb::SBAddress, SBSymbol, GetStartAddress, ());
  LLDB_REGISTER_METHOD(lldb::SBAddress, SBSymbol, GetEndAddress, ());
  LLDB_REGISTER_METHOD(uint32_t, SBSymbol, GetPrologueByteSize, ());
  LLDB_REGISTER_METHOD(lldb::SymbolType, SBSymbol, GetType, ());
  LLDB_REGISTER_METHOD(bool, SBSymbol, IsExternal, ());
  LLDB_REGISTER_METHOD(bool, SBSymbol, IsSynthetic, ());
}

}
}
