//===-- CommandObjectFrame.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 "CommandObjectFrame.h"
#include "lldb/Core/Debugger.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandOptionArgumentTable.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Interpreter/OptionGroupVariable.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/ValueType.h"
#include "lldb/ValueObject/ValueObject.h"
#include "lldb/lldb-enumerations.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"

#include <memory>
#include <optional>
#include <string>

using namespace lldb;
using namespace lldb_private;

#pragma mark CommandObjectFrameDiagnose

// CommandObjectFrameInfo

// CommandObjectFrameDiagnose

#define LLDB_OPTIONS_frame_diag
#include "CommandOptions.inc"

class CommandObjectFrameDiagnose : public CommandObjectParsed {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() { OptionParsingStarting(nullptr); }

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;
      switch (short_option) {
      case 'r':
        reg = ConstString(option_arg);
        break;

      case 'a': {
        address.emplace();
        if (option_arg.getAsInteger(0, *address)) {
          address.reset();
          error = Status::FromErrorStringWithFormat(
              "invalid address argument '%s'", option_arg.str().c_str());
        }
      } break;

      case 'o': {
        offset.emplace();
        if (option_arg.getAsInteger(0, *offset)) {
          offset.reset();
          error = Status::FromErrorStringWithFormat(
              "invalid offset argument '%s'", option_arg.str().c_str());
        }
      } break;

      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      address.reset();
      reg.reset();
      offset.reset();
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_frame_diag_options);
    }

    // Options.
    std::optional<lldb::addr_t> address;
    std::optional<ConstString> reg;
    std::optional<int64_t> offset;
  };

  CommandObjectFrameDiagnose(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame diagnose",
                            "Try to determine what path the current stop "
                            "location used to get to a register or address",
                            nullptr,
                            eCommandRequiresThread | eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused) {
    AddSimpleArgumentList(eArgTypeFrameIndex, eArgRepeatOptional);
  }

  ~CommandObjectFrameDiagnose() override = default;

  Options *GetOptions() override { return &m_options; }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    Thread *thread = m_exe_ctx.GetThreadPtr();
    StackFrameSP frame_sp = thread->GetSelectedFrame(SelectMostRelevantFrame);

    ValueObjectSP valobj_sp;

    if (m_options.address) {
      if (m_options.reg || m_options.offset) {
        result.AppendError(
            "`frame diagnose --address` is incompatible with other arguments.");
        return;
      }
      valobj_sp = frame_sp->GuessValueForAddress(*m_options.address);
    } else if (m_options.reg) {
      valobj_sp = frame_sp->GuessValueForRegisterAndOffset(
          *m_options.reg, m_options.offset.value_or(0));
    } else {
      StopInfoSP stop_info_sp = thread->GetStopInfo();
      if (!stop_info_sp) {
        result.AppendError("no arguments provided, and no stop info");
        return;
      }

      valobj_sp = StopInfo::GetCrashingDereference(stop_info_sp);
    }

    if (!valobj_sp) {
      result.AppendError("no diagnosis available");
      return;
    }

    result.GetValueObjectList().Append(valobj_sp);
    DumpValueObjectOptions::DeclPrintingHelper helper =
        [&valobj_sp](ConstString type, ConstString var,
                     const DumpValueObjectOptions &opts,
                     Stream &stream) -> bool {
      const ValueObject::GetExpressionPathFormat format = ValueObject::
          GetExpressionPathFormat::eGetExpressionPathFormatHonorPointers;
      valobj_sp->GetExpressionPath(stream, format);
      stream.PutCString(" =");
      return true;
    };

    DumpValueObjectOptions options;
    options.SetDeclPrintingHelper(helper);
    // We've already handled the case where the value object sp is null, so
    // this is just to make sure future changes don't skip that:
    assert(valobj_sp.get() && "Must have a valid ValueObject to print");
    ValueObjectPrinter printer(*valobj_sp, &result.GetOutputStream(), options);
    if (llvm::Error error = printer.PrintValueObject())
      result.AppendError(toString(std::move(error)));
    else
      result.SetStatus(eReturnStatusSuccessFinishResult);
  }

  CommandOptions m_options;
};

#pragma mark CommandObjectFrameInfo

// CommandObjectFrameInfo

class CommandObjectFrameInfo : public CommandObjectParsed {
public:
  CommandObjectFrameInfo(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame info",
                            "List information about the current "
                            "stack frame in the current thread.",
                            "frame info",
                            eCommandRequiresFrame | eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused) {}

  ~CommandObjectFrameInfo() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat(&result.GetOutputStream());
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

#pragma mark CommandObjectFrameSelect

// CommandObjectFrameSelect

#define LLDB_OPTIONS_frame_select
#include "CommandOptions.inc"

class CommandObjectFrameSelect : public CommandObjectParsed {
public:
  class CommandOptions : public Options {
  public:
    CommandOptions() { OptionParsingStarting(nullptr); }

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;
      switch (short_option) {
      case 'r': {
        int32_t offset = 0;
        if (option_arg.getAsInteger(0, offset) || offset == INT32_MIN) {
          error = Status::FromErrorStringWithFormat(
              "invalid frame offset argument '%s'", option_arg.str().c_str());
        } else
          relative_frame_offset = offset;
        break;
      }

      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      relative_frame_offset.reset();
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_frame_select_options);
    }

    std::optional<int32_t> relative_frame_offset;
  };

  CommandObjectFrameSelect(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame select",
                            "Select the current stack frame by "
                            "index from within the current thread "
                            "(see 'thread backtrace'.)",
                            nullptr,
                            eCommandRequiresThread | eCommandTryTargetAPILock |
                                eCommandProcessMustBeLaunched |
                                eCommandProcessMustBePaused) {
    AddSimpleArgumentList(eArgTypeFrameIndex, eArgRepeatOptional);
  }

  ~CommandObjectFrameSelect() override = default;

  Options *GetOptions() override { return &m_options; }

private:
  void SkipHiddenFrames(Thread &thread, uint32_t frame_idx) {
    uint32_t candidate_idx = frame_idx;
    const unsigned max_depth = 12;
    for (unsigned num_try = 0; num_try < max_depth; ++num_try) {
      if (candidate_idx == 0 && *m_options.relative_frame_offset == -1) {
        candidate_idx = UINT32_MAX;
        break;
      }
      candidate_idx += *m_options.relative_frame_offset;
      if (auto candidate_sp = thread.GetStackFrameAtIndex(candidate_idx)) {
        if (candidate_sp->IsHidden())
          continue;
        // Now candidate_idx is the first non-hidden frame.
        break;
      }
      candidate_idx = UINT32_MAX;
      break;
    };
    if (candidate_idx != UINT32_MAX)
      m_options.relative_frame_offset = candidate_idx - frame_idx;
  }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    // No need to check "thread" for validity as eCommandRequiresThread ensures
    // it is valid
    Thread *thread = m_exe_ctx.GetThreadPtr();

    uint32_t frame_idx = UINT32_MAX;
    if (m_options.relative_frame_offset) {
      // The one and only argument is a signed relative frame index
      frame_idx = thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
      if (frame_idx == UINT32_MAX)
        frame_idx = 0;

      // If moving up/down by one, skip over hidden frames, unless we started
      // in a hidden frame.
      if ((*m_options.relative_frame_offset == 1 ||
           *m_options.relative_frame_offset == -1)) {
        if (auto current_frame_sp = thread->GetStackFrameAtIndex(frame_idx);
            !current_frame_sp->IsHidden())
          SkipHiddenFrames(*thread, frame_idx);
      }

      if (*m_options.relative_frame_offset < 0) {
        if (static_cast<int32_t>(frame_idx) >=
            -*m_options.relative_frame_offset)
          frame_idx += *m_options.relative_frame_offset;
        else {
          if (frame_idx == 0) {
            // If you are already at the bottom of the stack, then just warn
            // and don't reset the frame.
            result.AppendError("already at the bottom of the stack");
            return;
          } else
            frame_idx = 0;
        }
      } else if (*m_options.relative_frame_offset > 0) {
        // I don't want "up 20" where "20" takes you past the top of the stack
        // to produce an error, but rather to just go to the top.  OTOH, start
        // by seeing if the requested frame exists, in which case we can avoid
        // counting the stack here...
        const uint32_t frame_requested =
            frame_idx + *m_options.relative_frame_offset;
        StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_requested);
        if (frame_sp)
          frame_idx = frame_requested;
        else {
          // The request went past the stack, so handle that case:
          const uint32_t num_frames = thread->GetStackFrameCount();
          if (static_cast<int32_t>(num_frames - frame_idx) >
              *m_options.relative_frame_offset) {
            frame_idx += *m_options.relative_frame_offset;
          } else {
            if (frame_idx == num_frames - 1) {
              // If we are already at the top of the stack, just warn and don't
              // reset the frame.
              result.AppendError("already at the top of the stack");
              return;
            } else
              frame_idx = num_frames - 1;
          }
        }
      }
    } else {
      if (command.GetArgumentCount() > 1) {
        result.AppendErrorWithFormat(
            "too many arguments; expected frame-index, saw '%s'",
            command[0].c_str());
        m_options.GenerateOptionUsage(
            result.GetErrorStream(), *this,
            GetCommandInterpreter().GetDebugger().GetTerminalWidth(),
            GetCommandInterpreter().GetDebugger().GetUseColor());
        return;
      }

      if (command.GetArgumentCount() == 1) {
        if (command[0].ref().getAsInteger(0, frame_idx)) {
          result.AppendErrorWithFormat("invalid frame index argument '%s'",
                                       command[0].c_str());
          return;
        }
      } else if (command.GetArgumentCount() == 0) {
        frame_idx = thread->GetSelectedFrameIndex(SelectMostRelevantFrame);
        if (frame_idx == UINT32_MAX) {
          frame_idx = 0;
        }
      }
    }

    bool success = thread->SetSelectedFrameByIndexNoisily(
        frame_idx, result.GetOutputStream());
    if (success) {
      m_exe_ctx.SetFrameSP(thread->GetSelectedFrame(SelectMostRelevantFrame));
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      result.AppendErrorWithFormat("Frame index (%u) out of range", frame_idx);
    }
  }

  CommandOptions m_options;
};

#pragma mark CommandObjectFrameVariable
// List images with associated information
class CommandObjectFrameVariable : public CommandObjectParsed {
public:
  CommandObjectFrameVariable(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "frame variable",
            "Show variables for the current stack frame. Defaults to all "
            "arguments and local variables in scope. Names of argument, "
            "local, file static and file global variables can be specified.",
            nullptr,
            eCommandRequiresFrame | eCommandTryTargetAPILock |
                eCommandProcessMustBeLaunched | eCommandProcessMustBePaused |
                eCommandRequiresProcess),
        m_option_variable(
            true), // Include the frame specific options by passing "true"
        m_option_format(eFormatDefault) {
    SetHelpLong(R"(
Children of aggregate variables can be specified such as 'var->child.x'.  In
'frame variable', the operators -> and [] do not invoke operator overloads if
they exist, but directly access the specified element.  If you want to trigger
operator overloads use the expression command to print the variable instead.

It is worth noting that except for overloaded operators, when printing local
variables 'expr local_var' and 'frame var local_var' produce the same results.
However, 'frame variable' is more efficient, since it uses debug information and
memory reads directly, rather than parsing and evaluating an expression, which
may even involve JITing and running code in the target program.)");

    AddSimpleArgumentList(eArgTypeVarName, eArgRepeatStar);

    m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Append(&m_option_format,
                          OptionGroupFormat::OPTION_GROUP_FORMAT |
                              OptionGroupFormat::OPTION_GROUP_GDB_FMT,
                          LLDB_OPT_SET_1);
    m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
    m_option_group.Finalize();
  }

  ~CommandObjectFrameVariable() override = default;

  Options *GetOptions() override { return &m_option_group; }

  // `frame variable` repeats by incrementing the printing depth. When the depth
  // is too shallow, hitting enter a few times will quickly expand the data.
  std::optional<std::string> GetRepeatCommand(Args &current_command_args,
                                              uint32_t index) override {
    llvm::StringRef depth_opt = "--depth";

    Args repeat_args;
    auto increment_option =
        [&](llvm::StringRef option) -> std::optional<std::string> {
      uint32_t num;
      bool failed = option.getAsInteger(10, num);
      if (failed)
        return std::nullopt;
      return llvm::utostr(num + 1);
    };

    bool has_depth_option = false;
    bool increment_next_arg = false;
    for (const auto &entry : current_command_args) {
      llvm::StringRef arg = entry.ref();

      if (arg == "-" || arg == "--") {
        repeat_args.AppendArgument(arg);
        continue;
      }

      if (increment_next_arg) {
        increment_next_arg = false;
        if (auto maybe_opt = increment_option(arg)) {
          repeat_args.AppendArgument(*maybe_opt);
          continue;
        }
      }

      if (depth_opt.starts_with(arg) || arg == "-D") {
        repeat_args.AppendArgument(arg);
        increment_next_arg = true;
        has_depth_option = true;
        continue;
      }
      if (arg.consume_front("-D")) {
        if (auto maybe_opt = increment_option(arg)) {
          repeat_args.AppendArgument(llvm::formatv("-D{0}", *maybe_opt).str());
          has_depth_option = true;
          continue;
        }
      }

      repeat_args.AppendArgument(arg);
    }

    if (!has_depth_option) {
      // Access the default max-depth from the target. This is because
      // GetRepeatCommand is called before ParseOptions, which is when
      // m_varobj_options.max_depth becomes assigned.
      if (auto target_sp = GetCommandInterpreter().GetSelectedTarget()) {
        auto [default_depth, _] =
            target_sp->GetMaximumDepthOfChildrenToDisplay();
        // Insert the depth after `frame variable`, before positional args.
        assert(repeat_args[0].ref() == "frame" && "expects resolved command");
        repeat_args.InsertArgumentAtIndex(2, "--depth");
        repeat_args.InsertArgumentAtIndex(3, llvm::utostr(default_depth + 1));
      }
    }

    std::string repeat_command;
    if (!repeat_args.GetQuotedCommandString(repeat_command))
      return std::nullopt;
    return repeat_command;
  }

protected:
  llvm::StringRef GetScopeString(VariableSP var_sp) {
    if (!var_sp)
      return llvm::StringRef();

    auto vt = var_sp->GetScope();
    bool is_synthetic = IsSyntheticValueType(vt);
    // Clear the bit so the rest works correctly.
    if (is_synthetic)
      vt = GetBaseValueType(vt);

    switch (vt) {
    case eValueTypeVariableGlobal:
      return is_synthetic ? "(synthetic) GLOBAL: " : "GLOBAL: ";
    case eValueTypeVariableStatic:
      return is_synthetic ? "(synthetic) STATIC: " : "STATIC: ";
    case eValueTypeVariableArgument:
      return is_synthetic ? "(synthetic) ARG: " : "ARG: ";
    case eValueTypeVariableLocal:
      return is_synthetic ? "(synthetic) LOCAL: " : "LOCAL: ";
    case eValueTypeVariableThreadLocal:
      return is_synthetic ? "(synthetic) THREAD: " : "THREAD: ";
    default:
      break;
    }

    return llvm::StringRef();
  }

  /// Returns true if `scope` matches any of the options in `m_option_variable`.
  bool ScopeRequested(lldb::ValueType scope) {
    // If it's a synthetic variable, check if we want to show those first.
    bool is_synthetic = IsSyntheticValueType(scope);
    if (is_synthetic) {
      if (!m_option_variable.show_synthetic)
        return false;

      scope = GetBaseValueType(scope);
    }
    switch (scope) {
    case eValueTypeVariableGlobal:
    case eValueTypeVariableStatic:
      return m_option_variable.show_globals;
    case eValueTypeVariableArgument:
      return m_option_variable.show_args;
    case eValueTypeVariableLocal:
      return m_option_variable.show_locals;
    case eValueTypeInvalid:
    case eValueTypeRegister:
    case eValueTypeRegisterSet:
    case eValueTypeConstResult:
    case eValueTypeVariableThreadLocal:
    case eValueTypeVTable:
    case eValueTypeVTableEntry:
      // The default for all other value types is is_synthetic. Aside from the
      // modifiers above that should apply equally to synthetic and normal
      // variables, any other synthetic variable we should default to showing.
      return is_synthetic;
    case eValueTypeSyntheticFlag:
      llvm_unreachable("This flag was unset");
    }
    llvm_unreachable("Unexpected scope value");
  }

  /// Finds all the variables in `all_variables` whose name matches `regex`,
  /// inserting them into `matches`. Variables already contained in `matches`
  /// are not inserted again.
  /// Nullopt is returned in case of no matches.
  /// A sub-range of `matches` with all newly inserted variables is returned.
  /// This may be empty if all matches were already contained in `matches`.
  std::optional<llvm::ArrayRef<VariableSP>>
  findUniqueRegexMatches(RegularExpression &regex,
                         VariableList &matches,
                         const VariableList &all_variables) {
    bool any_matches = false;
    const size_t previous_num_vars = matches.GetSize();

    for (const VariableSP &var : all_variables) {
      if (!var->NameMatches(regex) || !ScopeRequested(var->GetScope()))
        continue;
      any_matches = true;
      matches.AddVariableIfUnique(var);
    }

    if (any_matches)
      return matches.toArrayRef().drop_front(previous_num_vars);
    return std::nullopt;
  }

  void DoExecute(Args &command, CommandReturnObject &result) override {
    // No need to check "frame" for validity as eCommandRequiresFrame ensures
    // it is valid
    StackFrame *frame = m_exe_ctx.GetFramePtr();

    Stream &s = result.GetOutputStream();

    // Using a regex should behave like looking for an exact name match: it
    // also finds globals.
    m_option_variable.show_globals |= m_option_variable.use_regex;

    // Be careful about the stack frame, if any summary formatter runs code, it
    // might clear the StackFrameList for the thread.  So hold onto a shared
    // pointer to the frame so it stays alive.

    Status error;
    VariableList *variable_list =
        frame->GetVariableList(m_option_variable.show_globals,
                               m_option_variable.show_synthetic, &error);

    if (error.Fail() && (!variable_list || variable_list->GetSize() == 0)) {
      result.AppendError(error.AsCString());
    }

    ValueObjectSP valobj_sp;

    TypeSummaryImplSP summary_format_sp;
    if (!m_option_variable.summary.IsCurrentValueEmpty())
      DataVisualization::NamedSummaryFormats::GetSummaryFormat(
          ConstString(m_option_variable.summary.GetCurrentValue()),
          summary_format_sp);
    else if (!m_option_variable.summary_string.IsCurrentValueEmpty())
      summary_format_sp = std::make_shared<StringSummaryFormat>(
          TypeSummaryImpl::Flags(),
          m_option_variable.summary_string.GetCurrentValue());

    DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
        eLanguageRuntimeDescriptionDisplayVerbosityFull, eFormatDefault,
        summary_format_sp));

    const SymbolContext &sym_ctx =
        frame->GetSymbolContext(eSymbolContextFunction);
    if (sym_ctx.function && sym_ctx.function->IsTopLevelFunction())
      m_option_variable.show_globals = true;

    ValueObjectListSP recognized_arg_list;
    if (m_option_variable.show_recognized_args)
      if (auto recognized_frame = frame->GetRecognizedFrame())
        recognized_arg_list = recognized_frame->GetRecognizedArguments();

    const Format format = m_option_format.GetFormat();
    options.SetFormat(format);

    auto print_value = [&result, options](ValueObjectSP valobj_sp) {
      result.GetValueObjectList().Append(valobj_sp);
      if (auto error = valobj_sp->Dump(result.GetOutputStream(), options))
        result.AppendError(toString(std::move(error)));
    };

    if (variable_list) {
      if (!command.empty()) {
        VariableList regex_var_list;

        // If we have any args to the variable command, we will make variable
        // objects from them...
        for (auto &entry : command) {
          if (m_option_variable.use_regex) {
            llvm::StringRef name_str = entry.ref();
            RegularExpression regex(name_str);
            if (regex.IsValid()) {
              std::optional<llvm::ArrayRef<VariableSP>> results =
                  findUniqueRegexMatches(regex, regex_var_list, *variable_list);
              if (!results) {
                // No variables matched. Try recognized args as fallback.
                bool found_recognized = false;
                if (recognized_arg_list)
                  for (auto &rec_value_sp : recognized_arg_list->GetObjects())
                    if (regex.Execute(rec_value_sp->GetName())) {
                      found_recognized = true;
                      print_value(rec_value_sp);
                    }
                if (!found_recognized) {
                  result.AppendErrorWithFormat(
                      "no variables matched the regular expression '%s'",
                      entry.c_str());
                }
                continue;
              }
              for (const VariableSP &var_sp : *results) {
                valobj_sp = frame->GetValueObjectForFrameVariable(
                    var_sp, m_varobj_options.use_dynamic);
                if (valobj_sp) {
                  result.GetValueObjectList().Append(valobj_sp);

                  std::string scope_string;
                  if (m_option_variable.show_scope)
                    scope_string = GetScopeString(var_sp).str();

                  if (!scope_string.empty())
                    s.PutCString(scope_string);

                  if (m_option_variable.show_decl &&
                      var_sp->GetDeclaration().GetFile()) {
                    bool show_fullpaths = false;
                    bool show_module = true;
                    if (var_sp->DumpDeclaration(&s, show_fullpaths,
                                                show_module))
                      s.PutCString(": ");
                  }
                  auto &strm = result.GetOutputStream();
                  if (llvm::Error error = valobj_sp->Dump(strm, options))
                    result.AppendError(toString(std::move(error)));
                }
              }
            } else {
              if (llvm::Error err = regex.GetError())
                result.AppendError(llvm::toString(std::move(err)));
              else
                result.AppendErrorWithFormat(
                    "unknown regex error when compiling '%s'", entry.c_str());
            }
          } else // No regex, either exact variable names or variable
                 // expressions.
          {
            Status error;
            uint32_t expr_path_options =
                StackFrame::eExpressionPathOptionCheckPtrVsMember |
                StackFrame::eExpressionPathOptionsAllowDirectIVarAccess |
                StackFrame::eExpressionPathOptionsInspectAnonymousUnions |
                StackFrame::eExpressionPathOptionsAllowVarUpdates;
            lldb::VariableSP var_sp;
            valobj_sp = frame->GetValueForVariableExpressionPath(
                entry.ref(), m_varobj_options.use_dynamic, expr_path_options,
                var_sp, error);
            // Check only the `error` argument, because doing
            // `valobj_sp->GetError()` will update the value and potentially
            // return a new error that happens during the update, even if
            // `GetValueForVariableExpressionPath` reported no errors.
            if (valobj_sp && error.Success()) {
              result.GetValueObjectList().Append(valobj_sp);

              std::string scope_string;
              if (m_option_variable.show_scope)
                scope_string = GetScopeString(var_sp).str();

              if (!scope_string.empty())
                s.PutCString(scope_string);
              if (m_option_variable.show_decl && var_sp &&
                  var_sp->GetDeclaration().GetFile()) {
                var_sp->GetDeclaration().DumpStopContext(&s, false);
                s.PutCString(": ");
              }

              options.SetFormat(format);
              options.SetVariableFormatDisplayLanguage(
                  valobj_sp->GetPreferredDisplayLanguage());

              Stream &output_stream = result.GetOutputStream();
              options.SetRootValueObjectName(
                  valobj_sp->GetParent() ? entry.c_str() : nullptr);

              // If there is an error while updating the value, it will be
              // printed here as the contents of the value, e.g.
              // `(int) *((int*)0) = <parent is NULL>`
              if (llvm::Error error = valobj_sp->Dump(output_stream, options))
                result.AppendError(toString(std::move(error)));
            } else {
              // Variable lookup failed. Check recognized args as a fallback.
              bool found_recognized = false;
              if (recognized_arg_list)
                for (auto &obj_sp : recognized_arg_list->GetObjects())
                  if (obj_sp->GetName() == entry.ref()) {
                    found_recognized = true;
                    print_value(obj_sp);
                    break;
                  }
              if (!found_recognized) {
                if (error.Fail())
                  result.SetError(error.takeError());
                else
                  result.AppendErrorWithFormat(
                      "unable to find any variable expression path that "
                      "matches '%s'",
                      entry.c_str());
              }
            }
          }
        }
      } else // No command arg specified.  Use variable_list, instead.
      {
        const size_t num_variables = variable_list->GetSize();
        if (num_variables > 0) {
          for (size_t i = 0; i < num_variables; i++) {
            VariableSP var_sp = variable_list->GetVariableAtIndex(i);
            if (!ScopeRequested(var_sp->GetScope()))
                continue;
            std::string scope_string;
            if (m_option_variable.show_scope)
              scope_string = GetScopeString(var_sp).str();

            // Use the variable object code to make sure we are using the same
            // APIs as the public API will be using...
            valobj_sp = frame->GetValueObjectForFrameVariable(
                var_sp, m_varobj_options.use_dynamic);
            if (valobj_sp) {
              result.GetValueObjectList().Append(valobj_sp);

              // When dumping all variables, don't print any variables that are
              // not in scope to avoid extra unneeded output
              if (valobj_sp->IsInScope()) {
                if (!valobj_sp->GetTargetSP()
                         ->GetDisplayRuntimeSupportValues() &&
                    valobj_sp->IsRuntimeSupportValue())
                  continue;

                if (!scope_string.empty())
                  s.PutCString(scope_string);

                if (m_option_variable.show_decl &&
                    var_sp->GetDeclaration().GetFile()) {
                  var_sp->GetDeclaration().DumpStopContext(&s, false);
                  s.PutCString(": ");
                }

                options.SetFormat(format);
                options.SetVariableFormatDisplayLanguage(
                    valobj_sp->GetPreferredDisplayLanguage());
                options.SetRootValueObjectName(
                    var_sp ? var_sp->GetName().AsCString(nullptr) : nullptr);
                if (llvm::Error error =
                        valobj_sp->Dump(result.GetOutputStream(), options))
                  result.AppendError(toString(std::move(error)));
              }
            }
          }
        }
      }
      if (result.GetStatus() != eReturnStatusFailed)
        result.SetStatus(eReturnStatusSuccessFinishResult);
    }

    if (recognized_arg_list && (command.empty() || !variable_list))
      for (auto &rec_value_sp : recognized_arg_list->GetObjects())
        print_value(rec_value_sp);

    m_interpreter.PrintWarningsIfNecessary(result.GetOutputStream(),
                                           m_cmd_name);

    // Increment statistics.
    TargetStats &target_stats = GetTarget()->GetStatistics();
    if (result.Succeeded())
      target_stats.GetFrameVariableStats().NotifySuccess();
    else
      target_stats.GetFrameVariableStats().NotifyFailure();
  }

  OptionGroupOptions m_option_group;
  OptionGroupVariable m_option_variable;
  OptionGroupFormat m_option_format;
  OptionGroupValueObjectDisplay m_varobj_options;
};

#pragma mark CommandObjectFrameRecognizer

#define LLDB_OPTIONS_frame_recognizer_add
#include "CommandOptions.inc"

class CommandObjectFrameRecognizerAdd : public CommandObjectParsed {
private:
  class CommandOptions : public Options {
  public:
    CommandOptions() = default;
    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *execution_context) override {
      Status error;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'f': {
        bool value, success;
        value = OptionArgParser::ToBoolean(option_arg, true, &success);
        if (success) {
          m_first_instruction_only = value;
        } else {
          error = Status::FromErrorStringWithFormat(
              "invalid boolean value '%s' passed for -f option",
              option_arg.str().c_str());
        }
      } break;
      case 'l':
        m_class_name = std::string(option_arg);
        break;
      case 's':
        m_module = std::string(option_arg);
        break;
      case 'n':
        m_symbols.push_back(std::string(option_arg));
        break;
      case 'x':
        m_regex = true;
        break;
      default:
        llvm_unreachable("Unimplemented option");
      }

      return error;
    }

    void OptionParsingStarting(ExecutionContext *execution_context) override {
      m_module = "";
      m_symbols.clear();
      m_class_name = "";
      m_regex = false;
      m_first_instruction_only = true;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::ArrayRef(g_frame_recognizer_add_options);
    }

    // Instance variables to hold the values for command options.
    std::string m_class_name;
    std::string m_module;
    std::vector<std::string> m_symbols;
    bool m_regex;
    bool m_first_instruction_only;
  };

  CommandOptions m_options;

  Options *GetOptions() override { return &m_options; }

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override;

public:
  CommandObjectFrameRecognizerAdd(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame recognizer add",
                            "Add a new frame recognizer.", nullptr,
                            eCommandAllowsDummyTarget) {
    SetHelpLong(R"(
Frame recognizers allow for retrieving information about special frames based on
ABI, arguments or other special properties of that frame, even without source
code or debug info. Currently, one use case is to extract function arguments
that would otherwise be unaccesible, or augment existing arguments.

Adding a custom frame recognizer is possible by implementing a Python class
and using the 'frame recognizer add' command. The Python class should have a
'get_recognized_arguments' method and it will receive an argument of type
lldb.SBFrame representing the current frame that we are trying to recognize.
The method should return a (possibly empty) list of lldb.SBValue objects that
represent the recognized arguments.

An example of a recognizer that retrieves the file descriptor values from libc
functions 'read', 'write' and 'close' follows:

  class LibcFdRecognizer(object):
    def get_recognized_arguments(self, frame):
      if frame.name in ["read", "write", "close"]:
        fd = frame.EvaluateExpression("$arg1").unsigned
        target = frame.thread.process.target
        value = target.CreateValueFromExpression("fd", "(int)%d" % fd)
        return [value]
      return []

The file containing this implementation can be imported via 'command script
import' and then we can register this recognizer with 'frame recognizer add'.
It's important to restrict the recognizer to the libc library (which is
libsystem_kernel.dylib on macOS) to avoid matching functions with the same name
in other modules:

(lldb) command script import .../fd_recognizer.py
(lldb) frame recognizer add -l fd_recognizer.LibcFdRecognizer -n read -s libsystem_kernel.dylib

When the program is stopped at the beginning of the 'read' function in libc, we
can view the recognizer arguments in 'frame variable':

(lldb) b read
(lldb) r
Process 1234 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3
    frame #0: 0x00007fff06013ca0 libsystem_kernel.dylib`read
(lldb) frame variable
(int) fd = 3

    )");
  }
  ~CommandObjectFrameRecognizerAdd() override = default;
};

void CommandObjectFrameRecognizerAdd::DoExecute(Args &command,
                                                CommandReturnObject &result) {
#if LLDB_ENABLE_PYTHON
  if (m_options.m_class_name.empty()) {
    result.AppendErrorWithFormat("%s needs a Python class name (-l argument)",
                                 m_cmd_name.c_str());
    return;
  }

  if (m_options.m_module.empty()) {
    result.AppendErrorWithFormat("%s needs a module name (-s argument)",
                                 m_cmd_name.c_str());
    return;
  }

  if (m_options.m_symbols.empty()) {
    result.AppendErrorWithFormat(
        "%s needs at least one symbol name (-n argument)", m_cmd_name.c_str());
    return;
  }

  if (m_options.m_regex && m_options.m_symbols.size() > 1) {
    result.AppendErrorWithFormat(
        "%s needs only one symbol regular expression (-n argument)",
        m_cmd_name.c_str());
    return;
  }

  ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();

  if (interpreter &&
      !interpreter->CheckObjectExists(m_options.m_class_name.c_str())) {
    result.AppendWarning("the provided class does not exist - please define it "
                         "before attempting to use this frame recognizer");
  }

  StackFrameRecognizerSP recognizer_sp =
      StackFrameRecognizerSP(new ScriptedStackFrameRecognizer(
          interpreter, m_options.m_class_name.c_str()));
  if (m_options.m_regex) {
    auto module = std::make_shared<RegularExpression>(m_options.m_module);
    auto func =
        std::make_shared<RegularExpression>(m_options.m_symbols.front());
    GetTarget()->GetFrameRecognizerManager().AddRecognizer(
        recognizer_sp, module, func, Mangled::NamePreference::ePreferDemangled,
        m_options.m_first_instruction_only);
  } else {
    auto module = ConstString(m_options.m_module);
    std::vector<ConstString> symbols(m_options.m_symbols.begin(),
                                     m_options.m_symbols.end());
    GetTarget()->GetFrameRecognizerManager().AddRecognizer(
        recognizer_sp, module, symbols,
        Mangled::NamePreference::ePreferDemangled,
        m_options.m_first_instruction_only);
  }
#endif

  result.SetStatus(eReturnStatusSuccessFinishNoResult);
}

class CommandObjectFrameRecognizerClear : public CommandObjectParsed {
public:
  CommandObjectFrameRecognizerClear(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame recognizer clear",
                            "Delete all frame recognizers.", nullptr,
                            eCommandAllowsDummyTarget) {}

  ~CommandObjectFrameRecognizerClear() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    GetTarget()->GetFrameRecognizerManager().RemoveAllRecognizers();
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

static void
PrintRecognizerDetails(Stream &strm, const std::string &name, bool enabled,
                       const std::string &module,
                       llvm::ArrayRef<lldb_private::ConstString> symbols,
                       Mangled::NamePreference symbol_mangling, bool regexp) {
  if (!enabled)
    strm << "[disabled] ";

  strm << name << ", ";

  if (!module.empty())
    strm << "module " << module << ", ";

  switch (symbol_mangling) {
  case Mangled::NamePreference ::ePreferMangled:
    strm << "mangled symbol ";
    break;
  case Mangled::NamePreference ::ePreferDemangled:
    strm << "demangled symbol ";
    break;
  case Mangled::NamePreference ::ePreferDemangledWithoutArguments:
    strm << "demangled (no args) symbol ";
    break;
  }

  if (regexp)
    strm << "regex ";

  llvm::interleaveComma(symbols, strm);
}

// Base class for commands which accept a single frame recognizer as an argument
class CommandObjectWithFrameRecognizerArg : public CommandObjectParsed {
public:
  CommandObjectWithFrameRecognizerArg(CommandInterpreter &interpreter,
                                      const char *name,
                                      const char *help = nullptr,
                                      const char *syntax = nullptr,
                                      uint32_t flags = 0)
      : CommandObjectParsed(interpreter, name, help, syntax, flags) {
    AddSimpleArgumentList(eArgTypeRecognizerID);
  }

  void
  HandleArgumentCompletion(CompletionRequest &request,
                           OptionElementVector &opt_element_vector) override {
    if (request.GetCursorIndex() != 0)
      return;

    GetTarget()->GetFrameRecognizerManager().ForEach(
        [&request](uint32_t rid, bool enabled, std::string rname,
                   std::string module,
                   llvm::ArrayRef<lldb_private::ConstString> symbols,
                   Mangled::NamePreference symbol_mangling, bool regexp) {
          StreamString strm;
          if (rname.empty())
            rname = "(internal)";

          PrintRecognizerDetails(strm, rname, enabled, module, symbols,
                                 symbol_mangling, regexp);

          request.TryCompleteCurrentArg(std::to_string(rid), strm.GetString());
        });
  }

  virtual void DoExecuteWithId(CommandReturnObject &result,
                               uint32_t recognizer_id) = 0;

  void DoExecute(Args &command, CommandReturnObject &result) override {
    uint32_t recognizer_id;
    if (!llvm::to_integer(command.GetArgumentAtIndex(0), recognizer_id)) {
      result.AppendErrorWithFormat("'%s' is not a valid recognizer id",
                                   command.GetArgumentAtIndex(0));
      return;
    }

    DoExecuteWithId(result, recognizer_id);
  }
};

class CommandObjectFrameRecognizerEnable
    : public CommandObjectWithFrameRecognizerArg {
public:
  CommandObjectFrameRecognizerEnable(CommandInterpreter &interpreter)
      : CommandObjectWithFrameRecognizerArg(
            interpreter, "frame recognizer enable",
            "Enable a frame recognizer by id.", nullptr,
            eCommandAllowsDummyTarget) {
    AddSimpleArgumentList(eArgTypeRecognizerID);
  }

  ~CommandObjectFrameRecognizerEnable() override = default;

protected:
  void DoExecuteWithId(CommandReturnObject &result,
                       uint32_t recognizer_id) override {
    auto &recognizer_mgr = GetTarget()->GetFrameRecognizerManager();
    if (!recognizer_mgr.SetEnabledForID(recognizer_id, true)) {
      result.AppendErrorWithFormat("'%u' is not a valid recognizer id",
                                   recognizer_id);
      return;
    }
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

class CommandObjectFrameRecognizerDisable
    : public CommandObjectWithFrameRecognizerArg {
public:
  CommandObjectFrameRecognizerDisable(CommandInterpreter &interpreter)
      : CommandObjectWithFrameRecognizerArg(
            interpreter, "frame recognizer disable",
            "Disable a frame recognizer by id.", nullptr,
            eCommandAllowsDummyTarget) {
    AddSimpleArgumentList(eArgTypeRecognizerID);
  }

  ~CommandObjectFrameRecognizerDisable() override = default;

protected:
  void DoExecuteWithId(CommandReturnObject &result,
                       uint32_t recognizer_id) override {
    auto &recognizer_mgr = GetTarget()->GetFrameRecognizerManager();
    if (!recognizer_mgr.SetEnabledForID(recognizer_id, false)) {
      result.AppendErrorWithFormat("'%u' is not a valid recognizer id",
                                   recognizer_id);
      return;
    }
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

class CommandObjectFrameRecognizerDelete
    : public CommandObjectWithFrameRecognizerArg {
public:
  CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter)
      : CommandObjectWithFrameRecognizerArg(
            interpreter, "frame recognizer delete",
            "Delete an existing frame recognizer by id.", nullptr,
            eCommandAllowsDummyTarget) {
    AddSimpleArgumentList(eArgTypeRecognizerID);
  }

  ~CommandObjectFrameRecognizerDelete() override = default;

protected:
  void DoExecuteWithId(CommandReturnObject &result,
                       uint32_t recognizer_id) override {
    auto &recognizer_mgr = GetTarget()->GetFrameRecognizerManager();
    if (!recognizer_mgr.RemoveRecognizerWithID(recognizer_id)) {
      result.AppendErrorWithFormat("'%u' is not a valid recognizer id",
                                   recognizer_id);
      return;
    }
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

class CommandObjectFrameRecognizerList : public CommandObjectParsed {
public:
  CommandObjectFrameRecognizerList(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "frame recognizer list",
                            "Show a list of active frame recognizers.", nullptr,
                            eCommandAllowsDummyTarget) {}

  ~CommandObjectFrameRecognizerList() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    bool any_printed = false;
    GetTarget()->GetFrameRecognizerManager().ForEach(
        [&result,
         &any_printed](uint32_t recognizer_id, bool enabled, std::string name,
                       std::string module, llvm::ArrayRef<ConstString> symbols,
                       Mangled::NamePreference symbol_mangling, bool regexp) {
          Stream &stream = result.GetOutputStream();

          if (name.empty())
            name = "(internal)";

          stream << std::to_string(recognizer_id) << ": ";
          PrintRecognizerDetails(stream, name, enabled, module, symbols,
                                 symbol_mangling, regexp);

          stream.EOL();
          stream.Flush();

          any_printed = true;
        });

    if (any_printed)
      result.SetStatus(eReturnStatusSuccessFinishResult);
    else {
      result.GetOutputStream().PutCString("no matching results found.\n");
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
    }
  }
};

class CommandObjectFrameRecognizerInfo : public CommandObjectParsed {
public:
  CommandObjectFrameRecognizerInfo(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "frame recognizer info",
            "Show which frame recognizer is applied a stack frame (if any).",
            nullptr, eCommandAllowsDummyTarget) {
    AddSimpleArgumentList(eArgTypeFrameIndex);
  }

  ~CommandObjectFrameRecognizerInfo() override = default;

protected:
  void DoExecute(Args &command, CommandReturnObject &result) override {
    const char *frame_index_str = command.GetArgumentAtIndex(0);
    uint32_t frame_index;
    if (!llvm::to_integer(frame_index_str, frame_index)) {
      result.AppendErrorWithFormat("'%s' is not a valid frame index",
                                   frame_index_str);
      return;
    }

    Process *process = m_exe_ctx.GetProcessPtr();
    if (process == nullptr) {
      result.AppendError("no process");
      return;
    }
    Thread *thread = m_exe_ctx.GetThreadPtr();
    if (thread == nullptr) {
      result.AppendError("no thread");
      return;
    }
    if (command.GetArgumentCount() != 1) {
      result.AppendErrorWithFormat(
          "'%s' takes exactly one frame index argument", m_cmd_name.c_str());
      return;
    }

    StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_index);
    if (!frame_sp) {
      result.AppendErrorWithFormat("no frame with index %u", frame_index);
      return;
    }

    auto recognizer =
        GetTarget()->GetFrameRecognizerManager().GetRecognizerForFrame(
            frame_sp);

    Stream &output_stream = result.GetOutputStream();
    output_stream.Printf("frame %d ", frame_index);
    if (recognizer) {
      output_stream << "is recognized by ";
      output_stream << recognizer->GetName();
    } else {
      output_stream << "not recognized by any recognizer";
    }
    output_stream.EOL();
    result.SetStatus(eReturnStatusSuccessFinishResult);
  }
};

class CommandObjectFrameRecognizer : public CommandObjectMultiword {
public:
  CommandObjectFrameRecognizer(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "frame recognizer",
            "Commands for editing and viewing frame recognizers.",
            "frame recognizer [<sub-command-options>] ") {
    LoadSubCommand("info", CommandObjectSP(new CommandObjectFrameRecognizerInfo(
                               interpreter)));
    LoadSubCommand("list", CommandObjectSP(new CommandObjectFrameRecognizerList(
                               interpreter)));
    LoadSubCommand("add", CommandObjectSP(new CommandObjectFrameRecognizerAdd(
                              interpreter)));
    LoadSubCommand(
        "enable",
        CommandObjectSP(new CommandObjectFrameRecognizerEnable(interpreter)));
    LoadSubCommand(
        "disable",
        CommandObjectSP(new CommandObjectFrameRecognizerDisable(interpreter)));
    LoadSubCommand(
        "delete",
        CommandObjectSP(new CommandObjectFrameRecognizerDelete(interpreter)));
    LoadSubCommand(
        "clear",
        CommandObjectSP(new CommandObjectFrameRecognizerClear(interpreter)));
  }

  ~CommandObjectFrameRecognizer() override = default;
};

#pragma mark CommandObjectMultiwordFrame

// CommandObjectMultiwordFrame

CommandObjectMultiwordFrame::CommandObjectMultiwordFrame(
    CommandInterpreter &interpreter)
    : CommandObjectMultiword(interpreter, "frame",
                             "Commands for selecting and "
                             "examining the current "
                             "thread's stack frames.",
                             "frame <subcommand> [<subcommand-options>]") {
  LoadSubCommand("diagnose",
                 CommandObjectSP(new CommandObjectFrameDiagnose(interpreter)));
  LoadSubCommand("info",
                 CommandObjectSP(new CommandObjectFrameInfo(interpreter)));
  LoadSubCommand("select",
                 CommandObjectSP(new CommandObjectFrameSelect(interpreter)));
  LoadSubCommand("variable",
                 CommandObjectSP(new CommandObjectFrameVariable(interpreter)));
#if LLDB_ENABLE_PYTHON
  LoadSubCommand("recognizer", CommandObjectSP(new CommandObjectFrameRecognizer(
                                   interpreter)));
#endif
}

CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame() = default;
