//===----------------------------------------------------------------------===//
//
// 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 "ScriptedFrame.h"
#include "Plugins/Process/Utility/RegisterContextMemory.h"

#include "lldb/Core/Address.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Expression/DWARFExpressionList.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Interpreter/Interfaces/ScriptedFrameInterface.h"
#include "lldb/Interpreter/Interfaces/ScriptedInterface.h"
#include "lldb/Interpreter/Interfaces/ScriptedThreadInterface.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/DynamicRegisterInfo.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/ValueType.h"
#include "lldb/ValueObject/ValueObject.h"
#include "lldb/ValueObject/ValueObjectList.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "llvm/Support/ErrorHandling.h"

#include <memory>

using namespace lldb;
using namespace lldb_private;

char ScriptedFrame::ID;

void ScriptedFrame::CheckInterpreterAndScriptObject() const {
  lldbassert(m_script_object_sp && "Invalid Script Object.");
  lldbassert(GetInterface() && "Invalid Scripted Frame Interface.");
}

llvm::Expected<std::shared_ptr<ScriptedFrame>>
ScriptedFrame::Create(ThreadSP thread_sp,
                      ScriptedThreadInterfaceSP scripted_thread_interface_sp,
                      StructuredData::DictionarySP args_sp,
                      StructuredData::Generic *script_object) {
  if (!thread_sp || !thread_sp->IsValid())
    return llvm::createStringError("invalid thread");

  ProcessSP process_sp = thread_sp->GetProcess();
  if (!process_sp || !process_sp->IsValid())
    return llvm::createStringError("invalid process");

  ScriptInterpreter *script_interp =
      process_sp->GetTarget().GetDebugger().GetScriptInterpreter();
  if (!script_interp)
    return llvm::createStringError("no script interpreter");

  auto scripted_frame_interface = script_interp->CreateScriptedFrameInterface();
  if (!scripted_frame_interface)
    return llvm::createStringError("failed to create scripted frame interface");

  llvm::StringRef frame_class_name;
  if (!script_object) {
    // If no script object is provided and we have a scripted thread interface,
    // try to get the frame class name from it.
    if (scripted_thread_interface_sp) {
      std::optional<std::string> class_name =
          scripted_thread_interface_sp->GetScriptedFramePluginName();
      if (!class_name || class_name->empty())
        return llvm::createStringError(
            "failed to get scripted frame class name");
      frame_class_name = *class_name;
    } else {
      return llvm::createStringError(
          "no script object provided and no scripted thread interface");
    }
  }

  ExecutionContext exe_ctx(thread_sp);
  auto obj_or_err = scripted_frame_interface->CreatePluginObject(
      frame_class_name, exe_ctx, args_sp, script_object);

  if (!obj_or_err)
    return llvm::createStringError(
        "failed to create script object: %s",
        llvm::toString(obj_or_err.takeError()).c_str());

  StructuredData::GenericSP owned_script_object_sp = *obj_or_err;

  if (!owned_script_object_sp->IsValid())
    return llvm::createStringError("created script object is invalid");

  lldb::user_id_t frame_id = scripted_frame_interface->GetID();

  lldb::addr_t pc = scripted_frame_interface->GetPC();
  SymbolContext sc;
  Address symbol_addr;
  if (pc != LLDB_INVALID_ADDRESS) {
    symbol_addr.SetLoadAddress(pc, &process_sp->GetTarget());
    symbol_addr.CalculateSymbolContext(&sc);
  }

  std::optional<SymbolContext> maybe_sym_ctx =
      scripted_frame_interface->GetSymbolContext();
  if (maybe_sym_ctx)
    sc = *maybe_sym_ctx;

  lldb::RegisterContextSP reg_ctx_sp;
  auto regs_or_err =
      CreateRegisterContext(*scripted_frame_interface, *thread_sp, frame_id);
  if (!regs_or_err)
    LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), regs_or_err.takeError(), "{0}");
  else
    reg_ctx_sp = *regs_or_err;

  return std::make_shared<ScriptedFrame>(thread_sp, scripted_frame_interface,
                                         frame_id, pc, sc, reg_ctx_sp,
                                         owned_script_object_sp);
}

ScriptedFrame::ScriptedFrame(ThreadSP thread_sp,
                             ScriptedFrameInterfaceSP interface_sp,
                             lldb::user_id_t id, lldb::addr_t pc,
                             SymbolContext &sym_ctx,
                             lldb::RegisterContextSP reg_ctx_sp,
                             StructuredData::GenericSP script_object_sp)
    : StackFrame(thread_sp, /*frame_idx=*/id,
                 /*concrete_frame_idx=*/id, /*reg_context_sp=*/reg_ctx_sp,
                 /*cfa=*/0, /*pc=*/pc,
                 /*behaves_like_zeroth_frame=*/!id, /*symbol_ctx=*/&sym_ctx),
      m_scripted_frame_interface_sp(interface_sp),
      m_script_object_sp(script_object_sp) {
  // FIXME: This should be part of the base class constructor.
  m_stack_frame_kind = StackFrame::Kind::Synthetic;
}

ScriptedFrame::~ScriptedFrame() {}

const char *ScriptedFrame::GetFunctionName() {
  CheckInterpreterAndScriptObject();
  std::optional<std::string> function_name = GetInterface()->GetFunctionName();
  if (!function_name)
    return StackFrame::GetFunctionName();
  return ConstString(*function_name).AsCString(nullptr);
}

const char *ScriptedFrame::GetDisplayFunctionName() {
  CheckInterpreterAndScriptObject();
  std::optional<std::string> function_name =
      GetInterface()->GetDisplayFunctionName();
  if (!function_name)
    return StackFrame::GetDisplayFunctionName();
  return ConstString(*function_name).AsCString(nullptr);
}

bool ScriptedFrame::IsInlined() { return GetInterface()->IsInlined(); }

bool ScriptedFrame::IsArtificial() const {
  return GetInterface()->IsArtificial();
}

bool ScriptedFrame::IsHidden() { return GetInterface()->IsHidden(); }

lldb::ScriptedFrameInterfaceSP ScriptedFrame::GetInterface() const {
  return m_scripted_frame_interface_sp;
}

std::shared_ptr<DynamicRegisterInfo> ScriptedFrame::GetDynamicRegisterInfo() {
  CheckInterpreterAndScriptObject();

  StructuredData::DictionarySP reg_info = GetInterface()->GetRegisterInfo();

  Status error;
  if (!reg_info)
    return ScriptedInterface::ErrorWithMessage<
        std::shared_ptr<DynamicRegisterInfo>>(
        LLVM_PRETTY_FUNCTION, "failed to get scripted frame registers info",
        error, LLDBLog::Thread);

  ThreadSP thread_sp = m_thread_wp.lock();
  if (!thread_sp || !thread_sp->IsValid())
    return ScriptedInterface::ErrorWithMessage<
        std::shared_ptr<DynamicRegisterInfo>>(
        LLVM_PRETTY_FUNCTION,
        "failed to get scripted frame registers info: invalid thread", error,
        LLDBLog::Thread);

  ProcessSP process_sp = thread_sp->GetProcess();
  if (!process_sp || !process_sp->IsValid())
    return ScriptedInterface::ErrorWithMessage<
        std::shared_ptr<DynamicRegisterInfo>>(
        LLVM_PRETTY_FUNCTION,
        "failed to get scripted frame registers info: invalid process", error,
        LLDBLog::Thread);

  return DynamicRegisterInfo::Create(*reg_info,
                                     process_sp->GetTarget().GetArchitecture());
}

llvm::Expected<lldb::RegisterContextSP>
ScriptedFrame::CreateRegisterContext(ScriptedFrameInterface &interface,
                                     Thread &thread, lldb::user_id_t frame_id) {
  StructuredData::DictionarySP reg_info = interface.GetRegisterInfo();

  if (!reg_info)
    return llvm::createStringError(
        "failed to get scripted frame registers info");

  std::shared_ptr<DynamicRegisterInfo> register_info_sp =
      DynamicRegisterInfo::Create(
          *reg_info, thread.GetProcess()->GetTarget().GetArchitecture());

  lldb::RegisterContextSP reg_ctx_sp;

  std::optional<std::string> reg_data = interface.GetRegisterContext();
  if (!reg_data)
    return llvm::createStringError(
        "failed to get scripted frame registers data");

  DataBufferSP data_sp(
      std::make_shared<DataBufferHeap>(reg_data->c_str(), reg_data->size()));

  if (!data_sp->GetByteSize())
    return llvm::createStringError("failed to copy raw registers data");

  std::shared_ptr<RegisterContextMemory> reg_ctx_memory =
      std::make_shared<RegisterContextMemory>(
          thread, frame_id, *register_info_sp, LLDB_INVALID_ADDRESS);

  reg_ctx_memory->SetAllRegisterData(data_sp);
  reg_ctx_sp = reg_ctx_memory;

  return reg_ctx_sp;
}

lldb::RegisterContextSP ScriptedFrame::GetRegisterContext() {
  if (!m_reg_context_sp) {
    Status error;
    if (!m_scripted_frame_interface_sp)
      return ScriptedInterface::ErrorWithMessage<RegisterContextSP>(
          LLVM_PRETTY_FUNCTION,
          "failed to get scripted frame registers context: invalid interface",
          error, LLDBLog::Thread);

    ThreadSP thread_sp = GetThread();
    if (!thread_sp)
      return ScriptedInterface::ErrorWithMessage<RegisterContextSP>(
          LLVM_PRETTY_FUNCTION,
          "failed to get scripted frame registers context: invalid thread",
          error, LLDBLog::Thread);

    auto regs_or_err = CreateRegisterContext(*m_scripted_frame_interface_sp,
                                             *thread_sp, GetFrameIndex());
    if (!regs_or_err) {
      error = Status::FromError(regs_or_err.takeError());
      return ScriptedInterface::ErrorWithMessage<RegisterContextSP>(
          LLVM_PRETTY_FUNCTION,
          "failed to get scripted frame registers context", error,
          LLDBLog::Thread);
    }

    m_reg_context_sp = *regs_or_err;
  }

  return m_reg_context_sp;
}

VariableList *ScriptedFrame::GetVariableList(bool get_file_globals,
                                             bool include_synthetic_vars,
                                             Status *error_ptr) {
  PopulateVariableListFromInterface(include_synthetic_vars);
  return m_variable_list_sp.get();
}

lldb::VariableListSP
ScriptedFrame::GetInScopeVariableList(bool get_file_globals,
                                      bool include_synthetic_vars,
                                      bool must_have_valid_location) {
  PopulateVariableListFromInterface(include_synthetic_vars);
  return m_variable_list_sp;
}

void ScriptedFrame::PopulateVariableListFromInterface(
    bool include_synthetic_vars) {
  // Fetch values from the interface.
  ValueObjectListSP value_list_sp = GetInterface()->GetVariables();
  if (!value_list_sp)
    return;

  // Convert what we can into a variable.
  m_variable_list_sp = std::make_shared<VariableList>();

  for (uint32_t i = 0, e = value_list_sp->GetSize(); i < e; ++i) {
    ValueObjectSP v = value_list_sp->GetValueObjectAtIndex(i);
    if (!v)
      continue;

    // Ask the interface about the value type of this variable. If it doesn't
    // specify any, use the original value type.
    lldb::ValueType vt = GetInterface()->GetValueTypeForVariable(v).value_or(
        GetSyntheticValueType(v->GetValueType()));

    if (IsSyntheticValueType(vt) && !include_synthetic_vars)
      continue;

    // Just make up a variable - the frame variable dumper just passes it
    // back in to GetValueObjectForFrameVariable, so we really just need to
    // make sure the name and type are correct. We create IDs based on
    // value_list_sp in order to make sure they're unique.
    m_variable_list_sp->AddVariable(std::make_shared<lldb_private::Variable>(
        (lldb::user_id_t)value_list_sp->GetSize() + i,
        v->GetName().GetCString(), v->GetName().GetCString(), nullptr, vt,
        /*owner_scope=*/nullptr,
        /*scope_range=*/Variable::RangeList{},
        /*decl=*/nullptr, DWARFExpressionList{}, /*external=*/false,
        /*artificial=*/true, /*location_is_constant_data=*/false));
  }
}

lldb::ValueObjectSP ScriptedFrame::GetValueObjectForFrameVariable(
    const lldb::VariableSP &variable_sp, lldb::DynamicValueType use_dynamic) {
  // Fetch values from the interface.
  ValueObjectListSP values = m_scripted_frame_interface_sp->GetVariables();
  if (!values)
    return {};

  return values->FindValueObjectByValueName(
      variable_sp->GetName().AsCString(nullptr));
}

lldb::ValueObjectSP ScriptedFrame::FindVariable(ConstString name) {
  // Fetch values from the interface.
  ValueObjectListSP values = m_scripted_frame_interface_sp->GetVariables();
  if (!values)
    return {};

  return values->FindValueObjectByValueName(name.AsCString(nullptr));
}

lldb::ValueObjectSP ScriptedFrame::GetValueForVariableExpressionPath(
    llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
    uint32_t options, lldb::VariableSP &var_sp, Status &error,
    lldb::DILMode mode) {
  // Unless the frame implementation knows how to create variables (which it
  // doesn't), we can't construct anything for the variable. This may seem
  // somewhat out of place, but it's basically because of how this API is used -
  // the print command uses this API to fill in var_sp; and this implementation
  // can't do that!
  // FIXME: We should make it possible for the frame implementation to create
  //        Variable objects.
  (void)var_sp;
  // Otherwise, delegate to the scripted frame interface pointer.
  return m_scripted_frame_interface_sp->GetValueObjectForVariableExpression(
      var_expr, options, error);
}
