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

#include "lldb/Host/Config.h"

#include <stdio.h>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif

#include <cstdlib>
#include <map>
#include <string>

#include "lldb/Core/Module.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Expression/IRInterpreter.h"
#include "lldb/Expression/Materializer.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanCallUserExpression.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"

using namespace lldb_private;

char UserExpression::ID;

UserExpression::UserExpression(ExecutionContextScope &exe_scope,
                               llvm::StringRef expr, llvm::StringRef prefix,
                               lldb::LanguageType language,
                               ResultType desired_type,
                               const EvaluateExpressionOptions &options)
    : Expression(exe_scope), m_expr_text(std::string(expr)),
      m_expr_prefix(std::string(prefix)), m_language(language),
      m_desired_type(desired_type), m_options(options) {}

UserExpression::~UserExpression() {}

void UserExpression::InstallContext(ExecutionContext &exe_ctx) {
  m_jit_process_wp = exe_ctx.GetProcessSP();

  lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();

  if (frame_sp)
    m_address = frame_sp->GetFrameCodeAddress();
}

bool UserExpression::LockAndCheckContext(ExecutionContext &exe_ctx,
                                         lldb::TargetSP &target_sp,
                                         lldb::ProcessSP &process_sp,
                                         lldb::StackFrameSP &frame_sp) {
  lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock();
  process_sp = exe_ctx.GetProcessSP();

  if (process_sp != expected_process_sp)
    return false;

  process_sp = exe_ctx.GetProcessSP();
  target_sp = exe_ctx.GetTargetSP();
  frame_sp = exe_ctx.GetFrameSP();

  if (m_address.IsValid()) {
    if (!frame_sp)
      return false;
    return (Address::CompareLoadAddress(m_address,
                                        frame_sp->GetFrameCodeAddress(),
                                        target_sp.get()) == 0);
  }

  return true;
}

bool UserExpression::MatchesContext(ExecutionContext &exe_ctx) {
  lldb::TargetSP target_sp;
  lldb::ProcessSP process_sp;
  lldb::StackFrameSP frame_sp;

  return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp);
}

lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp,
                                              ConstString &object_name,
                                              Status &err) {
  err.Clear();

  if (!frame_sp) {
    err.SetErrorStringWithFormat(
        "Couldn't load '%s' because the context is incomplete",
        object_name.AsCString());
    return LLDB_INVALID_ADDRESS;
  }

  lldb::VariableSP var_sp;
  lldb::ValueObjectSP valobj_sp;

  valobj_sp = frame_sp->GetValueForVariableExpressionPath(
      object_name.GetStringRef(), lldb::eNoDynamicValues,
      StackFrame::eExpressionPathOptionCheckPtrVsMember |
          StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
          StackFrame::eExpressionPathOptionsNoSyntheticChildren |
          StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
      var_sp, err);

  if (!err.Success() || !valobj_sp.get())
    return LLDB_INVALID_ADDRESS;

  lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);

  if (ret == LLDB_INVALID_ADDRESS) {
    err.SetErrorStringWithFormat(
        "Couldn't load '%s' because its value couldn't be evaluated",
        object_name.AsCString());
    return LLDB_INVALID_ADDRESS;
  }

  return ret;
}

lldb::ExpressionResults
UserExpression::Evaluate(ExecutionContext &exe_ctx,
                         const EvaluateExpressionOptions &options,
                         llvm::StringRef expr, llvm::StringRef prefix,
                         lldb::ValueObjectSP &result_valobj_sp, Status &error,
                         std::string *fixed_expression, ValueObject *ctx_obj) {
  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS |
                                                  LIBLLDB_LOG_STEP));

  if (ctx_obj) {
    static unsigned const ctx_type_mask =
        lldb::TypeFlags::eTypeIsClass | lldb::TypeFlags::eTypeIsStructUnion;
    if (!(ctx_obj->GetTypeInfo() & ctx_type_mask)) {
      LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a context object of "
                    "an invalid type, can't run expressions.");
      error.SetErrorString("a context object of an invalid type passed");
      return lldb::eExpressionSetupError;
    }
  }

  lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
  lldb::LanguageType language = options.GetLanguage();
  const ResultType desired_type = options.DoesCoerceToId()
                                      ? UserExpression::eResultTypeId
                                      : UserExpression::eResultTypeAny;
  lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;

  Target *target = exe_ctx.GetTargetPtr();
  if (!target) {
    LLDB_LOG(log, "== [UserExpression::Evaluate] Passed a NULL target, can't "
                  "run expressions.");
    error.SetErrorString("expression passed a null target");
    return lldb::eExpressionSetupError;
  }

  Process *process = exe_ctx.GetProcessPtr();

  if (process == nullptr || process->GetState() != lldb::eStateStopped) {
    if (execution_policy == eExecutionPolicyAlways) {
      LLDB_LOG(log, "== [UserExpression::Evaluate] Expression may not run, but "
                    "is not constant ==");

      error.SetErrorString("expression needed to run but couldn't");

      return execution_results;
    }
  }

  // Explicitly force the IR interpreter to evaluate the expression when the
  // there is no process that supports running the expression for us. Don't
  // change the execution policy if we have the special top-level policy that
  // doesn't contain any expression and there is nothing to interpret.
  if (execution_policy != eExecutionPolicyTopLevel &&
      (process == nullptr || !process->CanJIT()))
    execution_policy = eExecutionPolicyNever;

  // We need to set the expression execution thread here, turns out parse can
  // call functions in the process of looking up symbols, which will escape the
  // context set by exe_ctx passed to Execute.
  lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP();
  ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(
      thread_sp);

  llvm::StringRef full_prefix;
  llvm::StringRef option_prefix(options.GetPrefix());
  std::string full_prefix_storage;
  if (!prefix.empty() && !option_prefix.empty()) {
    full_prefix_storage = std::string(prefix);
    full_prefix_storage.append(std::string(option_prefix));
    full_prefix = full_prefix_storage;
  } else if (!prefix.empty())
    full_prefix = prefix;
  else
    full_prefix = option_prefix;

  // If the language was not specified in the expression command, set it to the
  // language in the target's properties if specified, else default to the
  // langage for the frame.
  if (language == lldb::eLanguageTypeUnknown) {
    if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
      language = target->GetLanguage();
    else if (StackFrame *frame = exe_ctx.GetFramePtr())
      language = frame->GetLanguage();
  }

  lldb::UserExpressionSP user_expression_sp(
      target->GetUserExpressionForLanguage(expr, full_prefix, language,
                                           desired_type, options, ctx_obj,
                                           error));
  if (error.Fail()) {
    LLDB_LOG(log, "== [UserExpression::Evaluate] Getting expression: {0} ==",
             error.AsCString());
    return lldb::eExpressionSetupError;
  }

  LLDB_LOG(log, "== [UserExpression::Evaluate] Parsing expression {0} ==",
           expr.str());

  const bool keep_expression_in_memory = true;
  const bool generate_debug_info = options.GetGenerateDebugInfo();

  if (options.InvokeCancelCallback(lldb::eExpressionEvaluationParse)) {
    error.SetErrorString("expression interrupted by callback before parse");
    result_valobj_sp = ValueObjectConstResult::Create(
        exe_ctx.GetBestExecutionContextScope(), error);
    return lldb::eExpressionInterrupted;
  }

  DiagnosticManager diagnostic_manager;

  bool parse_success =
      user_expression_sp->Parse(diagnostic_manager, exe_ctx, execution_policy,
                                keep_expression_in_memory, generate_debug_info);

  // Calculate the fixed expression always, since we need it for errors.
  std::string tmp_fixed_expression;
  if (fixed_expression == nullptr)
    fixed_expression = &tmp_fixed_expression;

  const char *fixed_text = user_expression_sp->GetFixedText();
  if (fixed_text != nullptr)
    fixed_expression->append(fixed_text);

  // If there is a fixed expression, try to parse it:
  if (!parse_success) {
    // Delete the expression that failed to parse before attempting to parse
    // the next expression.
    user_expression_sp.reset();

    execution_results = lldb::eExpressionParseError;
    if (fixed_expression && !fixed_expression->empty() &&
        options.GetAutoApplyFixIts()) {
      const uint64_t max_fix_retries = options.GetRetriesWithFixIts();
      for (uint64_t i = 0; i < max_fix_retries; ++i) {
        // Try parsing the fixed expression.
        lldb::UserExpressionSP fixed_expression_sp(
            target->GetUserExpressionForLanguage(
                fixed_expression->c_str(), full_prefix, language, desired_type,
                options, ctx_obj, error));
        DiagnosticManager fixed_diagnostic_manager;
        parse_success = fixed_expression_sp->Parse(
            fixed_diagnostic_manager, exe_ctx, execution_policy,
            keep_expression_in_memory, generate_debug_info);
        if (parse_success) {
          diagnostic_manager.Clear();
          user_expression_sp = fixed_expression_sp;
          break;
        } else {
          // The fixed expression also didn't parse. Let's check for any new
          // Fix-Its we could try.
          if (fixed_expression_sp->GetFixedText()) {
            *fixed_expression = fixed_expression_sp->GetFixedText();
          } else {
            // Fixed expression didn't compile without a fixit, don't retry and
            // don't tell the user about it.
            fixed_expression->clear();
            break;
          }
        }
      }
    }

    if (!parse_success) {
      if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts()) {
        error.SetExpressionErrorWithFormat(
            execution_results,
            "expression failed to parse, fixed expression suggested:\n  %s",
            fixed_expression->c_str());
      } else {
        if (!diagnostic_manager.Diagnostics().size())
          error.SetExpressionError(execution_results,
                                   "expression failed to parse, unknown error");
        else
          error.SetExpressionError(execution_results,
                                   diagnostic_manager.GetString().c_str());
      }
    }
  }

  if (parse_success) {
    lldb::ExpressionVariableSP expr_result;

    if (execution_policy == eExecutionPolicyNever &&
        !user_expression_sp->CanInterpret()) {
      LLDB_LOG(log, "== [UserExpression::Evaluate] Expression may not run, but "
                    "is not constant ==");

      if (!diagnostic_manager.Diagnostics().size())
        error.SetExpressionError(lldb::eExpressionSetupError,
                                 "expression needed to run but couldn't");
    } else if (execution_policy == eExecutionPolicyTopLevel) {
      error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
      return lldb::eExpressionCompleted;
    } else {
      if (options.InvokeCancelCallback(lldb::eExpressionEvaluationExecution)) {
        error.SetExpressionError(
            lldb::eExpressionInterrupted,
            "expression interrupted by callback before execution");
        result_valobj_sp = ValueObjectConstResult::Create(
            exe_ctx.GetBestExecutionContextScope(), error);
        return lldb::eExpressionInterrupted;
      }

      diagnostic_manager.Clear();

      LLDB_LOG(log, "== [UserExpression::Evaluate] Executing expression ==");

      execution_results =
          user_expression_sp->Execute(diagnostic_manager, exe_ctx, options,
                                      user_expression_sp, expr_result);

      if (execution_results != lldb::eExpressionCompleted) {
        LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed "
                      "abnormally ==");

        if (!diagnostic_manager.Diagnostics().size())
          error.SetExpressionError(
              execution_results, "expression failed to execute, unknown error");
        else
          error.SetExpressionError(execution_results,
                                   diagnostic_manager.GetString().c_str());
      } else {
        if (expr_result) {
          result_valobj_sp = expr_result->GetValueObject();
          result_valobj_sp->SetPreferredDisplayLanguage(language);

          LLDB_LOG(log,
                   "== [UserExpression::Evaluate] Execution completed "
                   "normally with result {0} ==",
                   result_valobj_sp->GetValueAsCString());
        } else {
          LLDB_LOG(log, "== [UserExpression::Evaluate] Execution completed "
                        "normally with no result ==");

          error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
        }
      }
    }
  }

  if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) {
    error.SetExpressionError(
        lldb::eExpressionInterrupted,
        "expression interrupted by callback after complete");
    return lldb::eExpressionInterrupted;
  }

  if (result_valobj_sp.get() == nullptr) {
    result_valobj_sp = ValueObjectConstResult::Create(
        exe_ctx.GetBestExecutionContextScope(), error);
  }

  return execution_results;
}

lldb::ExpressionResults
UserExpression::Execute(DiagnosticManager &diagnostic_manager,
                        ExecutionContext &exe_ctx,
                        const EvaluateExpressionOptions &options,
                        lldb::UserExpressionSP &shared_ptr_to_me,
                        lldb::ExpressionVariableSP &result_var) {
  lldb::ExpressionResults expr_result = DoExecute(
      diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var);
  Target *target = exe_ctx.GetTargetPtr();
  if (options.GetResultIsInternal() && result_var && target) {
    if (auto *persistent_state =
            target->GetPersistentExpressionStateForLanguage(m_language))
      persistent_state->RemovePersistentVariable(result_var);
  }
  return expr_result;
}
