//===-- SBFrame.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 <algorithm>
#include <set>
#include <string>

#include "lldb/API/SBFrame.h"

#include "lldb/lldb-types.h"

#include "Utils.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/StackID.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Instrumentation.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Stream.h"
#include "lldb/ValueObject/ValueObjectConstResult.h"
#include "lldb/ValueObject/ValueObjectRegister.h"
#include "lldb/ValueObject/ValueObjectVariable.h"

#include "lldb/API/SBAddress.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBExpressionOptions.h"
#include "lldb/API/SBFormat.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBSymbolContext.h"
#include "lldb/API/SBThread.h"
#include "lldb/API/SBValue.h"
#include "lldb/API/SBVariablesOptions.h"

#include "llvm/Support/PrettyStackTrace.h"

using namespace lldb;
using namespace lldb_private;

SBFrame::SBFrame() : m_opaque_sp(new ExecutionContextRef()) {
  LLDB_INSTRUMENT_VA(this);
}

SBFrame::SBFrame(const StackFrameSP &lldb_object_sp)
    : m_opaque_sp(new ExecutionContextRef(lldb_object_sp)) {
  LLDB_INSTRUMENT_VA(this, lldb_object_sp);
}

SBFrame::SBFrame(const SBFrame &rhs) {
  LLDB_INSTRUMENT_VA(this, rhs);

  m_opaque_sp = clone(rhs.m_opaque_sp);
}

SBFrame::~SBFrame() = default;

const SBFrame &SBFrame::operator=(const SBFrame &rhs) {
  LLDB_INSTRUMENT_VA(this, rhs);

  if (this != &rhs)
    m_opaque_sp = clone(rhs.m_opaque_sp);
  return *this;
}

StackFrameSP SBFrame::GetFrameSP() const {
  return (m_opaque_sp ? m_opaque_sp->GetFrameSP() : StackFrameSP());
}

void SBFrame::SetFrameSP(const StackFrameSP &lldb_object_sp) {
  return m_opaque_sp->SetFrameSP(lldb_object_sp);
}

bool SBFrame::IsValid() const {
  LLDB_INSTRUMENT_VA(this);
  return this->operator bool();
}
SBFrame::operator bool() const {
  LLDB_INSTRUMENT_VA(this);
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return false;
  }

  return GetFrameSP().get() != nullptr;
}

SBSymbolContext SBFrame::GetSymbolContext(uint32_t resolve_scope) const {
  LLDB_INSTRUMENT_VA(this, resolve_scope);

  SBSymbolContext sb_sym_ctx;

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return sb_sym_ctx;
  }

  SymbolContextItem scope = static_cast<SymbolContextItem>(resolve_scope);
  if (StackFrame *frame = exe_ctx->GetFramePtr())
    sb_sym_ctx = frame->GetSymbolContext(scope);

  return sb_sym_ctx;
}

SBModule SBFrame::GetModule() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBModule();
  }

  ModuleSP module_sp;
  StackFrame *frame = exe_ctx->GetFramePtr();
  if (!frame)
    return SBModule();

  SBModule sb_module;
  module_sp = frame->GetSymbolContext(eSymbolContextModule).module_sp;
  sb_module.SetSP(module_sp);
  return sb_module;
}

SBCompileUnit SBFrame::GetCompileUnit() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBCompileUnit();
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return SBCompileUnit(
        frame->GetSymbolContext(eSymbolContextCompUnit).comp_unit);
  return SBCompileUnit();
}

SBFunction SBFrame::GetFunction() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBFunction();
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return SBFunction(frame->GetSymbolContext(eSymbolContextFunction).function);
  return SBFunction();
}

SBSymbol SBFrame::GetSymbol() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBSymbol();
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return SBSymbol(frame->GetSymbolContext(eSymbolContextSymbol).symbol);
  return SBSymbol();
}

SBBlock SBFrame::GetBlock() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBBlock();
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return SBBlock(frame->GetSymbolContext(eSymbolContextBlock).block);
  return SBBlock();
}

SBBlock SBFrame::GetFrameBlock() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBBlock();
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return SBBlock(frame->GetFrameBlock());
  return SBBlock();
}

SBLineEntry SBFrame::GetLineEntry() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBLineEntry();
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return SBLineEntry(
        &frame->GetSymbolContext(eSymbolContextLineEntry).line_entry);
  return SBLineEntry();
}

uint32_t SBFrame::GetFrameID() const {
  LLDB_INSTRUMENT_VA(this);

  constexpr uint32_t error_frame_idx = UINT32_MAX;

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return error_frame_idx;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return frame->GetFrameIndex();
  return error_frame_idx;
}

lldb::addr_t SBFrame::GetCFA() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return LLDB_INVALID_ADDRESS;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return frame->GetStackID().GetCallFrameAddressWithoutMetadata();
  return LLDB_INVALID_ADDRESS;
}

addr_t SBFrame::GetPC() const {
  LLDB_INSTRUMENT_VA(this);

  addr_t addr = LLDB_INVALID_ADDRESS;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return addr;
  }

  Target *target = exe_ctx->GetTargetPtr();
  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return frame->GetFrameCodeAddress().GetOpcodeLoadAddress(
        target, AddressClass::eCode);

  return addr;
}

bool SBFrame::SetPC(addr_t new_pc) {
  LLDB_INSTRUMENT_VA(this, new_pc);

  constexpr bool error_ret_val = false;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return error_ret_val;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext())
      return reg_ctx_sp->SetPC(new_pc);

  return error_ret_val;
}

addr_t SBFrame::GetSP() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return LLDB_INVALID_ADDRESS;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext())
      return reg_ctx_sp->GetSP();

  return LLDB_INVALID_ADDRESS;
}

addr_t SBFrame::GetFP() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return LLDB_INVALID_ADDRESS;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    if (RegisterContextSP reg_ctx_sp = frame->GetRegisterContext())
      return reg_ctx_sp->GetFP();

  return LLDB_INVALID_ADDRESS;
}

SBAddress SBFrame::GetPCAddress() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBAddress();
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return SBAddress(frame->GetFrameCodeAddress());
  return SBAddress();
}

void SBFrame::Clear() {
  LLDB_INSTRUMENT_VA(this);

  m_opaque_sp->Clear();
}

lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path,
                                               lldb::DILMode mode) {
  LLDB_INSTRUMENT_VA(this, var_path);

  SBValue sb_value;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return sb_value;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr()) {
    lldb::DynamicValueType use_dynamic =
        frame->CalculateTarget()->GetPreferDynamicValue();
    sb_value = GetValueForVariablePath(var_path, use_dynamic, mode);
  }
  return sb_value;
}

lldb::SBValue SBFrame::GetValueForVariablePath(const char *var_path,
                                               DynamicValueType use_dynamic,
                                               lldb::DILMode mode) {
  LLDB_INSTRUMENT_VA(this, var_path, use_dynamic);

  SBValue sb_value;
  if (var_path == nullptr || var_path[0] == '\0') {
    return sb_value;
  }

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return sb_value;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr()) {
    VariableSP var_sp;
    Status error;
    ValueObjectSP value_sp(frame->GetValueForVariableExpressionPath(
        var_path, eNoDynamicValues,
        StackFrame::eExpressionPathOptionCheckPtrVsMember |
            StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
        var_sp, error, mode));
    sb_value.SetSP(value_sp, use_dynamic);
  }
  return sb_value;
}

SBValue SBFrame::FindVariable(const char *name) {
  LLDB_INSTRUMENT_VA(this, name);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBValue();
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr()) {
    lldb::DynamicValueType use_dynamic =
        frame->CalculateTarget()->GetPreferDynamicValue();
    return FindVariable(name, use_dynamic);
  }
  return SBValue();
}

SBValue SBFrame::FindVariable(const char *name,
                              lldb::DynamicValueType use_dynamic) {
  LLDB_INSTRUMENT_VA(this, name, use_dynamic);

  VariableSP var_sp;
  SBValue sb_value;

  if (name == nullptr || name[0] == '\0') {
    return sb_value;
  }

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return sb_value;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    if (ValueObjectSP value_sp = frame->FindVariable(ConstString(name)))
      sb_value.SetSP(value_sp, use_dynamic);

  return sb_value;
}

SBValue SBFrame::FindValue(const char *name, ValueType value_type) {
  LLDB_INSTRUMENT_VA(this, name, value_type);

  SBValue value;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return value;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr()) {
    lldb::DynamicValueType use_dynamic =
        frame->CalculateTarget()->GetPreferDynamicValue();
    value = FindValue(name, value_type, use_dynamic);
  }
  return value;
}

SBValue SBFrame::FindValue(const char *name, ValueType value_type,
                           lldb::DynamicValueType use_dynamic) {
  LLDB_INSTRUMENT_VA(this, name, value_type, use_dynamic);

  SBValue sb_value;

  if (name == nullptr || name[0] == '\0') {
    return sb_value;
  }

  ValueObjectSP value_sp;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);

  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return value_sp;
  }

  StackFrame *frame = exe_ctx->GetFramePtr();
  if (!frame)
    return value_sp;

  VariableList variable_list;

  switch (value_type) {
  case eValueTypeVariableGlobal:        // global variable
  case eValueTypeVariableStatic:        // static variable
  case eValueTypeVariableArgument:      // function argument variables
  case eValueTypeVariableLocal:         // function local variables
  case eValueTypeVariableThreadLocal: { // thread local variables
    SymbolContext sc(frame->GetSymbolContext(eSymbolContextBlock));

    const bool can_create = true;
    const bool get_parent_variables = true;
    const bool stop_if_block_is_inlined_function = true;

    if (sc.block)
      sc.block->AppendVariables(
          can_create, get_parent_variables, stop_if_block_is_inlined_function,
          [frame](Variable *v) { return v->IsInScope(frame); }, &variable_list);
    if (value_type == eValueTypeVariableGlobal ||
        value_type == eValueTypeVariableStatic) {
      const bool get_file_globals = true;
      VariableList *frame_vars =
          frame->GetVariableList(get_file_globals, nullptr);
      if (frame_vars)
        frame_vars->AppendVariablesIfUnique(variable_list);
    }
    ConstString const_name(name);
    VariableSP variable_sp(variable_list.FindVariable(const_name, value_type));
    if (variable_sp) {
      value_sp =
          frame->GetValueObjectForFrameVariable(variable_sp, eNoDynamicValues);
      sb_value.SetSP(value_sp, use_dynamic);
    }
  } break;

  case eValueTypeRegister: { // stack frame register value
    if (RegisterContextSP reg_ctx = frame->GetRegisterContext()) {
      if (const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name)) {
        value_sp = ValueObjectRegister::Create(frame, reg_ctx, reg_info);
        sb_value.SetSP(value_sp);
      }
    }
  } break;

  case eValueTypeRegisterSet: { // A collection of stack frame register
                                // values
    if (RegisterContextSP reg_ctx = frame->GetRegisterContext()) {
      const uint32_t num_sets = reg_ctx->GetRegisterSetCount();
      for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) {
        const RegisterSet *reg_set = reg_ctx->GetRegisterSet(set_idx);
        if (reg_set &&
            (llvm::StringRef(reg_set->name).equals_insensitive(name) ||
             llvm::StringRef(reg_set->short_name).equals_insensitive(name))) {
          value_sp = ValueObjectRegisterSet::Create(frame, reg_ctx, set_idx);
          sb_value.SetSP(value_sp);
          break;
        }
      }
    }
  } break;

  case eValueTypeConstResult: { // constant result variables
    ConstString const_name(name);
    Target *target = exe_ctx->GetTargetPtr();
    ExpressionVariableSP expr_var_sp(target->GetPersistentVariable(const_name));
    if (expr_var_sp) {
      value_sp = expr_var_sp->GetValueObject();
      sb_value.SetSP(value_sp, use_dynamic);
    }
  } break;

  default:
    break;
  }

  return sb_value;
}

bool SBFrame::IsEqual(const SBFrame &that) const {
  LLDB_INSTRUMENT_VA(this, that);

  lldb::StackFrameSP this_sp = GetFrameSP();
  lldb::StackFrameSP that_sp = that.GetFrameSP();
  return (this_sp && that_sp && this_sp->GetStackID() == that_sp->GetStackID());
}

bool SBFrame::operator==(const SBFrame &rhs) const {
  LLDB_INSTRUMENT_VA(this, rhs);

  return IsEqual(rhs);
}

bool SBFrame::operator!=(const SBFrame &rhs) const {
  LLDB_INSTRUMENT_VA(this, rhs);

  return !IsEqual(rhs);
}

SBThread SBFrame::GetThread() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBThread();
  }

  ThreadSP thread_sp(exe_ctx->GetThreadSP());
  SBThread sb_thread(thread_sp);

  return sb_thread;
}

const char *SBFrame::Disassemble() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return nullptr;
  }

  if (auto *frame = exe_ctx->GetFramePtr())
    return ConstString(frame->Disassemble()).GetCString();

  return nullptr;
}

SBValueList SBFrame::GetVariables(bool arguments, bool locals, bool statics,
                                  bool in_scope_only) {
  LLDB_INSTRUMENT_VA(this, arguments, locals, statics, in_scope_only);

  SBValueList value_list;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return value_list;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr()) {
    Target *target = exe_ctx->GetTargetPtr();
    lldb::DynamicValueType use_dynamic =
        frame->CalculateTarget()->GetPreferDynamicValue();
    const bool include_runtime_support_values =
        target->GetDisplayRuntimeSupportValues();

    SBVariablesOptions options;
    options.SetIncludeArguments(arguments);
    options.SetIncludeLocals(locals);
    options.SetIncludeStatics(statics);
    options.SetInScopeOnly(in_scope_only);
    options.SetIncludeRuntimeSupportValues(include_runtime_support_values);
    options.SetUseDynamic(use_dynamic);

    value_list = GetVariables(options);
  }
  return value_list;
}

lldb::SBValueList SBFrame::GetVariables(bool arguments, bool locals,
                                        bool statics, bool in_scope_only,
                                        lldb::DynamicValueType use_dynamic) {
  LLDB_INSTRUMENT_VA(this, arguments, locals, statics, in_scope_only,
                     use_dynamic);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBValueList();
  }

  Target *target = exe_ctx->GetTargetPtr();
  const bool include_runtime_support_values =
      target->GetDisplayRuntimeSupportValues();
  SBVariablesOptions options;
  options.SetIncludeArguments(arguments);
  options.SetIncludeLocals(locals);
  options.SetIncludeStatics(statics);
  options.SetInScopeOnly(in_scope_only);
  options.SetIncludeRuntimeSupportValues(include_runtime_support_values);
  options.SetUseDynamic(use_dynamic);
  return GetVariables(options);
}

/// Returns true if the variable is in any of the requested scopes.
static bool IsInRequestedScope(bool statics, bool arguments, bool locals,
                               Variable &var) {
  switch (var.GetScope()) {
  case eValueTypeVariableGlobal:
  case eValueTypeVariableStatic:
  case eValueTypeVariableThreadLocal:
    return statics;

  case eValueTypeVariableArgument:
    return arguments;

  case eValueTypeVariableLocal:
    return locals;

  default:
    break;
  }
  return false;
}

enum WasInterrupted { Yes, No };

/// Populates `value_list` with the variables from `frame` according to
/// `options`. This method checks whether the Debugger received an interrupt
/// before processing every variable, returning `WasInterrupted::yes` in that
/// case.
static std::pair<WasInterrupted, Status> FetchVariablesUnlessInterrupted(
    const lldb::SBVariablesOptions &options, StackFrame &frame,
    SBValueList &value_list, Debugger &dbg,
    std::function<SBValue(ValueObjectSP, bool)> to_sbvalue) {
  const bool statics = options.GetIncludeStatics();
  const bool arguments = options.GetIncludeArguments();
  const bool locals = options.GetIncludeLocals();
  const bool in_scope_only = options.GetInScopeOnly();
  const bool include_runtime_support_values =
      options.GetIncludeRuntimeSupportValues();
  const lldb::DynamicValueType use_dynamic = options.GetUseDynamic();

  Status var_error;
  VariableList *variable_list = frame.GetVariableList(true, &var_error);

  std::set<VariableSP> variable_set;

  if (!variable_list)
    return {WasInterrupted::No, std::move(var_error)};
  const size_t num_variables = variable_list->GetSize();
  size_t num_produced = 0;
  for (const VariableSP &variable_sp : *variable_list) {
    if (!variable_sp ||
        !IsInRequestedScope(statics, arguments, locals, *variable_sp))
      continue;

    if (INTERRUPT_REQUESTED(
            dbg,
            "Interrupted getting frame variables with {0} of {1} "
            "produced.",
            num_produced, num_variables))
      return {WasInterrupted::Yes, std::move(var_error)};

    // Only add variables once so we don't end up with duplicates
    if (variable_set.insert(variable_sp).second == false)
      continue;
    if (in_scope_only && !variable_sp->IsInScope(&frame))
      continue;

    ValueObjectSP valobj_sp(
        frame.GetValueObjectForFrameVariable(variable_sp, eNoDynamicValues));

    if (!include_runtime_support_values && valobj_sp != nullptr &&
        valobj_sp->IsRuntimeSupportValue())
      continue;

    value_list.Append(to_sbvalue(valobj_sp, use_dynamic));
  }
  num_produced++;

  return {WasInterrupted::No, std::move(var_error)};
}

/// Populates `value_list` with recognized arguments of `frame` according to
/// `options`.
static llvm::SmallVector<ValueObjectSP>
FetchRecognizedArguments(const SBVariablesOptions &options, StackFrame &frame,
                         SBTarget target) {
  if (!options.GetIncludeRecognizedArguments(target))
    return {};
  RecognizedStackFrameSP recognized_frame = frame.GetRecognizedFrame();
  if (!recognized_frame)
    return {};

  ValueObjectListSP recognized_arg_list =
      recognized_frame->GetRecognizedArguments();
  if (!recognized_arg_list)
    return {};

  return llvm::to_vector(recognized_arg_list->GetObjects());
}

SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) {
  LLDB_INSTRUMENT_VA(this, options);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBValueList();
  }

  StackFrame *frame = exe_ctx->GetFramePtr();
  if (!frame)
    return SBValueList();

  auto valobj_to_sbvalue = [](ValueObjectSP valobj, bool use_dynamic) {
    SBValue value_sb;
    value_sb.SetSP(valobj, use_dynamic);
    return value_sb;
  };
  SBValueList value_list;
  std::pair<WasInterrupted, Status> fetch_result =
      FetchVariablesUnlessInterrupted(options, *frame, value_list,
                                      exe_ctx->GetTargetPtr()->GetDebugger(),
                                      valobj_to_sbvalue);
  if (fetch_result.second.Fail())
    value_list.SetError(std::move(fetch_result.second));

  if (fetch_result.first == WasInterrupted::Yes)
    return value_list;

  const lldb::DynamicValueType use_dynamic = options.GetUseDynamic();
  llvm::SmallVector<ValueObjectSP> args = FetchRecognizedArguments(
      options, *frame, SBTarget(exe_ctx->GetTargetSP()));
  for (ValueObjectSP arg : args) {
    SBValue value_sb;
    value_sb.SetSP(arg, use_dynamic);
    value_list.Append(value_sb);
  }
  return value_list;
}

SBValueList SBFrame::GetRegisters() {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBValueList();
  }

  StackFrame *frame = exe_ctx->GetFramePtr();
  if (!frame)
    return SBValueList();

  RegisterContextSP reg_ctx(frame->GetRegisterContext());
  if (!reg_ctx)
    return SBValueList();

  SBValueList value_list;
  const uint32_t num_sets = reg_ctx->GetRegisterSetCount();
  for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx)
    value_list.Append(ValueObjectRegisterSet::Create(frame, reg_ctx, set_idx));

  return value_list;
}

SBValue SBFrame::FindRegister(const char *name) {
  LLDB_INSTRUMENT_VA(this, name);

  ValueObjectSP value_sp;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return SBValue();
  }

  StackFrame *frame = exe_ctx->GetFramePtr();
  if (!frame)
    return SBValue();

  RegisterContextSP reg_ctx(frame->GetRegisterContext());
  if (!reg_ctx)
    return SBValue();

  const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name);
  if (!reg_info)
    return SBValue();

  SBValue result;
  value_sp = ValueObjectRegister::Create(frame, reg_ctx, reg_info);
  result.SetSP(value_sp);

  return result;
}

SBError SBFrame::GetDescriptionWithFormat(const SBFormat &format,
                                          SBStream &output) {
  Stream &strm = output.ref();

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx)
    return Status::FromError(exe_ctx.takeError());

  SBError error;

  if (!format) {
    error.SetErrorString("The provided SBFormat object is invalid");
    return error;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr();
      frame && frame->DumpUsingFormat(strm, format.GetFormatEntrySP().get()))
    return error;
  error.SetErrorStringWithFormat(
      "It was not possible to generate a frame "
      "description with the given format string '%s'",
      format.GetFormatEntrySP()->string.c_str());
  return error;
}

bool SBFrame::GetDescription(SBStream &description) {
  LLDB_INSTRUMENT_VA(this, description);

  Stream &strm = description.ref();

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    strm.PutCString("Error: process is not stopped.");
    return true;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    frame->DumpUsingSettingsFormat(&strm);

  return true;
}

SBValue SBFrame::EvaluateExpression(const char *expr) {
  LLDB_INSTRUMENT_VA(this, expr);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return CreateProcessIsRunningExprEvalError();
  }

  SBExpressionOptions options;
  StackFrame *frame = exe_ctx->GetFramePtr();
  if (frame) {
    lldb::DynamicValueType fetch_dynamic_value =
        frame->CalculateTarget()->GetPreferDynamicValue();
    options.SetFetchDynamicValue(fetch_dynamic_value);
  }
  options.SetUnwindOnError(true);
  options.SetIgnoreBreakpoints(true);
  Target *target = exe_ctx->GetTargetPtr();
  SourceLanguage language = target->GetLanguage();
  if (!language && frame)
    language = frame->GetLanguage();
  options.SetLanguage((SBSourceLanguageName)language.name, language.version);
  return EvaluateExpression(expr, options);
}

SBValue
SBFrame::EvaluateExpression(const char *expr,
                            lldb::DynamicValueType fetch_dynamic_value) {
  LLDB_INSTRUMENT_VA(this, expr, fetch_dynamic_value);

  SBExpressionOptions options;
  options.SetFetchDynamicValue(fetch_dynamic_value);
  options.SetUnwindOnError(true);
  options.SetIgnoreBreakpoints(true);
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return CreateProcessIsRunningExprEvalError();
  }

  StackFrame *frame = exe_ctx->GetFramePtr();
  Target *target = exe_ctx->GetTargetPtr();
  SourceLanguage language = target->GetLanguage();
  if (!language && frame)
    language = frame->GetLanguage();
  options.SetLanguage((SBSourceLanguageName)language.name, language.version);
  return EvaluateExpression(expr, options);
}

SBValue SBFrame::EvaluateExpression(const char *expr,
                                    lldb::DynamicValueType fetch_dynamic_value,
                                    bool unwind_on_error) {
  LLDB_INSTRUMENT_VA(this, expr, fetch_dynamic_value, unwind_on_error);

  SBExpressionOptions options;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return CreateProcessIsRunningExprEvalError();
  }

  options.SetFetchDynamicValue(fetch_dynamic_value);
  options.SetUnwindOnError(unwind_on_error);
  options.SetIgnoreBreakpoints(true);
  StackFrame *frame = exe_ctx->GetFramePtr();
  Target *target = exe_ctx->GetTargetPtr();
  SourceLanguage language = target->GetLanguage();
  if (!language && frame)
    language = frame->GetLanguage();
  options.SetLanguage((SBSourceLanguageName)language.name, language.version);
  return EvaluateExpression(expr, options);
}

lldb::SBValue SBFrame::CreateProcessIsRunningExprEvalError() {
  auto error = Status::FromErrorString("can't evaluate expressions when the "
                                       "process is running.");
  ValueObjectSP expr_value_sp =
      ValueObjectConstResult::Create(nullptr, std::move(error));
  SBValue expr_result;
  expr_result.SetSP(expr_value_sp, false);
  return expr_result;
}

lldb::SBValue SBFrame::EvaluateExpression(const char *expr,
                                          const SBExpressionOptions &options) {
  LLDB_INSTRUMENT_VA(this, expr, options);

  auto LogResult = [](SBValue expr_result) {
    Log *expr_log = GetLog(LLDBLog::Expressions);
    if (expr_result.GetError().Success())
      LLDB_LOGF(expr_log,
                "** [SBFrame::EvaluateExpression] Expression result is "
                "%s, summary %s **",
                expr_result.GetValue(), expr_result.GetSummary());
    else
      LLDB_LOGF(
          expr_log,
          "** [SBFrame::EvaluateExpression] Expression evaluation failed: "
          "%s **",
          expr_result.GetError().GetCString());
  };

  if (expr == nullptr || expr[0] == '\0') {
    return SBValue();
  }

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    SBValue error_result = CreateProcessIsRunningExprEvalError();
    LogResult(error_result);
    return error_result;
  }

  StackFrame *frame = exe_ctx->GetFramePtr();
  if (!frame)
    return SBValue();

  std::unique_ptr<llvm::PrettyStackTraceFormat> stack_trace;
  Target *target = exe_ctx->GetTargetPtr();
  if (target->GetDisplayExpressionsInCrashlogs()) {
    StreamString frame_description;
    frame->DumpUsingSettingsFormat(&frame_description);
    stack_trace = std::make_unique<llvm::PrettyStackTraceFormat>(
        "SBFrame::EvaluateExpression (expr = \"%s\", fetch_dynamic_value "
        "= %u) %s",
        expr, options.GetFetchDynamicValue(), frame_description.GetData());
  }

  ValueObjectSP expr_value_sp;
  target->EvaluateExpression(expr, frame, expr_value_sp, options.ref());

  SBValue expr_result;
  expr_result.SetSP(expr_value_sp, options.GetFetchDynamicValue());
  LogResult(expr_result);

  return expr_result;
}

SBStructuredData SBFrame::GetLanguageSpecificData() const {
  LLDB_INSTRUMENT_VA(this);

  SBStructuredData sb_data;
  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return sb_data;
  }
  StackFrame *frame = exe_ctx->GetFramePtr();
  if (!frame)
    return sb_data;

  StructuredData::ObjectSP data(frame->GetLanguageSpecificData());
  sb_data.m_impl_up->SetObjectSP(data);
  return sb_data;
}

bool SBFrame::IsInlined() {
  LLDB_INSTRUMENT_VA(this);

  return static_cast<const SBFrame *>(this)->IsInlined();
}

bool SBFrame::IsInlined() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return false;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return frame->IsInlined();
  return false;
}

bool SBFrame::IsArtificial() {
  LLDB_INSTRUMENT_VA(this);

  return static_cast<const SBFrame *>(this)->IsArtificial();
}

bool SBFrame::IsArtificial() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return false;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return frame->IsArtificial();

  return false;
}

bool SBFrame::IsSynthetic() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return false;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return frame->IsSynthetic();

  return false;
}

bool SBFrame::IsHidden() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return false;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return frame->IsHidden();

  return false;
}

const char *SBFrame::GetFunctionName() {
  LLDB_INSTRUMENT_VA(this);

  return static_cast<const SBFrame *>(this)->GetFunctionName();
}

lldb::LanguageType SBFrame::GuessLanguage() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return eLanguageTypeUnknown;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return frame->GuessLanguage().AsLanguageType();
  return eLanguageTypeUnknown;
}

const char *SBFrame::GetFunctionName() const {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return nullptr;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return frame->GetFunctionName();
  return nullptr;
}

const char *SBFrame::GetDisplayFunctionName() {
  LLDB_INSTRUMENT_VA(this);

  llvm::Expected<StoppedExecutionContext> exe_ctx =
      GetStoppedExecutionContext(m_opaque_sp);
  if (!exe_ctx) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), exe_ctx.takeError(), "{0}");
    return nullptr;
  }

  if (StackFrame *frame = exe_ctx->GetFramePtr())
    return frame->GetDisplayFunctionName();
  return nullptr;
}
