//===-- LLVMUserExpression.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/Expression/LLVMUserExpression.h"
#include "lldb/Core/Module.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/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/VariableList.h"
#include "lldb/Target/ABI.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/ErrorMessages.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Policy.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/ValueObject/ValueObjectConstResult.h"

using namespace lldb;
using namespace lldb_private;

char LLVMUserExpression::ID;

LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope,
                                       llvm::StringRef expr,
                                       llvm::StringRef prefix,
                                       SourceLanguage language,
                                       ResultType desired_type,
                                       const EvaluateExpressionOptions &options)
    : UserExpression(exe_scope, expr, prefix, language, desired_type, options),
      m_stack_frame_bottom(LLDB_INVALID_ADDRESS),
      m_stack_frame_top(LLDB_INVALID_ADDRESS), m_allow_cxx(false),
      m_allow_objc(false), m_transformed_text(), m_execution_unit_sp(),
      m_materializer_up(), m_jit_module_wp(), m_target(nullptr),
      m_can_interpret(false), m_materialized_address(LLDB_INVALID_ADDRESS) {}

LLVMUserExpression::~LLVMUserExpression() {
  if (m_target) {
    lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock());
    if (jit_module_sp)
      m_target->GetImages().Remove(jit_module_sp);
  }
}

lldb::ExpressionResults
LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager,
                              ExecutionContext &exe_ctx,
                              const EvaluateExpressionOptions &options,
                              lldb::UserExpressionSP &shared_ptr_to_me,
                              lldb::ExpressionVariableSP &result_sp) {
  // The expression log is quite verbose, and if you're just tracking the
  // execution of the expression, it's quite convenient to have these logs come
  // out with the STEP log as well.
  Log *log(GetLog(LLDBLog::Expressions | LLDBLog::Step));

  if (m_jit_start_addr == LLDB_INVALID_ADDRESS && !m_can_interpret) {
    diagnostic_manager.PutString(
        lldb::eSeverityError,
        "Expression can't be run, because there is no JIT compiled function");
    return lldb::eExpressionSetupError;
  }

  lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;

  if (!PrepareToExecuteJITExpression(diagnostic_manager, exe_ctx,
                                     struct_address)) {
    diagnostic_manager.Printf(
        lldb::eSeverityError,
        "errored out in %s, couldn't PrepareToExecuteJITExpression",
        __FUNCTION__);
    return lldb::eExpressionSetupError;
  }

  lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
  lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;

  lldb::ValueObjectSP error_backstop_result_sp;

  if (m_can_interpret) {
    llvm::Module *module = m_execution_unit_sp->GetModule();
    llvm::Function *function = m_execution_unit_sp->GetFunction();

    if (!module || !function) {
      diagnostic_manager.PutString(
          lldb::eSeverityError, "supposed to interpret, but nothing is there");
      return lldb::eExpressionSetupError;
    }

    Status interpreter_error;

    std::vector<lldb::addr_t> args;

    if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) {
      diagnostic_manager.Printf(lldb::eSeverityError,
                                "errored out in %s, couldn't AddArguments",
                                __FUNCTION__);
      return lldb::eExpressionSetupError;
    }

    function_stack_bottom = m_stack_frame_bottom;
    function_stack_top = m_stack_frame_top;

    IRInterpreter::Interpret(*module, *function, args, *m_execution_unit_sp,
                             interpreter_error, function_stack_bottom,
                             function_stack_top, exe_ctx, options.GetTimeout());

    if (!interpreter_error.Success()) {
      diagnostic_manager.Printf(lldb::eSeverityError,
                                "supposed to interpret, but failed: %s",
                                interpreter_error.AsCString());
      return lldb::eExpressionDiscarded;
    }
  } else {
    if (!exe_ctx.HasThreadScope()) {
      diagnostic_manager.Printf(lldb::eSeverityError,
                                "%s called with no thread selected",
                                __FUNCTION__);
      return lldb::eExpressionSetupError;
    }

    // Store away the thread ID for error reporting, in case it exits
    // during execution:
    lldb::tid_t expr_thread_id = exe_ctx.GetThreadRef().GetID();

    Address wrapper_address(m_jit_start_addr);

    std::vector<lldb::addr_t> args;

    if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) {
      diagnostic_manager.Printf(lldb::eSeverityError,
                                "errored out in %s, couldn't AddArguments",
                                __FUNCTION__);
      return lldb::eExpressionSetupError;
    }

    lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression(
        exe_ctx.GetThreadRef(), wrapper_address, args, options,
        shared_ptr_to_me));

    StreamString ss;
    if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) {
      diagnostic_manager.PutString(lldb::eSeverityError, ss.GetString());
      return lldb::eExpressionSetupError;
    }

    ThreadPlanCallUserExpression *user_expression_plan =
        static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());

    lldb::addr_t function_stack_pointer =
        user_expression_plan->GetFunctionStackPointer();

    function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
    function_stack_top = function_stack_pointer;

    LLDB_LOGF(log,
              "-- [UserExpression::Execute] Execution of expression begins --");

    if (exe_ctx.GetProcessPtr())
      exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);

    PolicyStack::Guard expr_policy_guard =
        PolicyStack::Get().PushPublicStateRunningExpression();

    lldb::ExpressionResults execution_result =
        exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options,
                                              diagnostic_manager);

    if (exe_ctx.GetProcessPtr())
      exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);

    LLDB_LOGF(log, "-- [UserExpression::Execute] Execution of expression "
                   "completed --");

    if (execution_result == lldb::eExpressionInterrupted ||
        execution_result == lldb::eExpressionHitBreakpoint) {
      const char *error_desc = nullptr;
      const char *explanation = execution_result == lldb::eExpressionInterrupted
                                    ? "was interrupted"
                                    : "hit a breakpoint";

      if (user_expression_plan) {
        if (auto real_stop_info_sp = user_expression_plan->GetRealStopInfo())
          error_desc = real_stop_info_sp->GetDescription();
      }

      if (error_desc)
        diagnostic_manager.Printf(lldb::eSeverityError,
                                  "Expression execution %s: %s.", explanation,
                                  error_desc);
      else
        diagnostic_manager.Printf(lldb::eSeverityError,
                                  "Expression execution %s.", explanation);

      if ((execution_result == lldb::eExpressionInterrupted &&
           options.DoesUnwindOnError()) ||
          (execution_result == lldb::eExpressionHitBreakpoint &&
           options.DoesIgnoreBreakpoints()))
        diagnostic_manager.AppendMessageToDiagnostic(
            "The process has been returned to the state before expression "
            "evaluation.");
      else {
        if (execution_result == lldb::eExpressionHitBreakpoint)
          user_expression_plan->TransferExpressionOwnership();
        diagnostic_manager.AppendMessageToDiagnostic(
            "The process has been left at the point where it was "
            "interrupted, use \"thread return -x\" to return to the state "
            "before expression evaluation.");
      }

      return execution_result;
    }

    if (execution_result == lldb::eExpressionStoppedForDebug) {
      diagnostic_manager.PutString(
          lldb::eSeverityInfo,
          "Expression execution was halted at the first instruction of the "
          "expression function because \"debug\" was requested.\n"
          "Use \"thread return -x\" to return to the state before expression "
          "evaluation.");
      return execution_result;
    }

    if (execution_result == lldb::eExpressionCompleted &&
        user_expression_plan->HitErrorBackstop()) {
      lldb::ValueObjectSP error_sp =
          user_expression_plan->GetReturnValueObject();
      if (error_sp && error_sp->GetError().Success())
        error_backstop_result_sp = error_sp;
    }

    if (execution_result == lldb::eExpressionThreadVanished) {
      diagnostic_manager.Printf(lldb::eSeverityError,
                                "Couldn't execute expression: the thread on "
                                "which the expression was being run (0x%" PRIx64
                                ") exited during its execution.",
                                expr_thread_id);
      return execution_result;
    }

    if (execution_result != lldb::eExpressionCompleted) {
      diagnostic_manager.Printf(lldb::eSeverityError,
                                "Couldn't execute expression: result was %s",
                                toString(execution_result).c_str());
      return execution_result;
    }
  }

  if (error_backstop_result_sp) {
    Target *target = exe_ctx.GetTargetPtr();
    PersistentExpressionState *expression_state =
        target->GetPersistentExpressionStateForLanguage(
            Language().AsLanguageType());
    if (expression_state)
      result_sp =
          expression_state->CreatePersistentVariable(error_backstop_result_sp);

    return lldb::eExpressionCompleted;
  }

  if (FinalizeJITExecution(diagnostic_manager, exe_ctx, result_sp,
                           function_stack_bottom, function_stack_top))
    return lldb::eExpressionCompleted;

  return lldb::eExpressionResultUnavailable;
}

bool LLVMUserExpression::FinalizeJITExecution(
    DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
    lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom,
    lldb::addr_t function_stack_top) {
  Log *log = GetLog(LLDBLog::Expressions);

  LLDB_LOGF(log, "-- [UserExpression::FinalizeJITExecution] Dematerializing "
                 "after execution --");

  if (!m_dematerializer_sp) {
    diagnostic_manager.Printf(lldb::eSeverityError,
                              "Couldn't apply expression side effects : no "
                              "dematerializer is present");
    return false;
  }

  Status dematerialize_error;

  m_dematerializer_sp->Dematerialize(dematerialize_error, function_stack_bottom,
                                     function_stack_top);

  if (!dematerialize_error.Success()) {
    diagnostic_manager.Printf(lldb::eSeverityError,
                              "Couldn't apply expression side effects : %s",
                              dematerialize_error.AsCString("unknown error"));
    return false;
  }

  result =
      GetResultAfterDematerialization(exe_ctx.GetBestExecutionContextScope());

  if (result) {
    // TransferAddress also does the offset_to_top calculation, so record the
    // dynamic option before we do that.
    if (EvaluateExpressionOptions *options = GetOptions())
      result->PreserveDynamicOption(options->GetUseDynamic());
    result->TransferAddress();
  }

  m_dematerializer_sp.reset();

  return true;
}

bool LLVMUserExpression::PrepareToExecuteJITExpression(
    DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
    lldb::addr_t &struct_address) {
  lldb::TargetSP target;
  lldb::ProcessSP process;
  lldb::StackFrameSP frame;

  if (!LockAndCheckContext(exe_ctx, target, process, frame)) {
    diagnostic_manager.PutString(
        lldb::eSeverityError,
        "The context has changed before we could JIT the expression!");
    return false;
  }

  // Early out if no JIT'd expr and can't interpret.
  if (m_jit_start_addr == LLDB_INVALID_ADDRESS && !m_can_interpret)
    return true;

  if (!PrepareArgumentStruct(diagnostic_manager, frame, struct_address))
    return false;

  if (m_can_interpret && !AllocateInterpreterStackFrame(diagnostic_manager,
                                                        *target, process.get()))
    return false;

  return true;
}

bool LLVMUserExpression::AllocateInterpreterStackFrame(
    DiagnosticManager &diagnostic_manager, Target &target, Process *process) {
  if (m_stack_frame_bottom != LLDB_INVALID_ADDRESS)
    return true;

  size_t stack_frame_size = target.GetExprAllocSize();
  if (stack_frame_size == 0) {
    ABISP abi_sp;
    if (process && (abi_sp = process->GetABI()))
      stack_frame_size = abi_sp->GetStackFrameSize();
    else
      stack_frame_size = 512 * 1024;
  }

  const bool zero_memory = false;
  if (auto address_or_error = m_execution_unit_sp->Malloc(
          stack_frame_size, 8,
          lldb::ePermissionsReadable | lldb::ePermissionsWritable,
          IRMemoryMap::eAllocationPolicyHostOnly, zero_memory)) {
    m_stack_frame_bottom = *address_or_error;
    m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
    return true;
  } else {
    diagnostic_manager.Printf(lldb::eSeverityError,
                              "Couldn't allocate space for the stack frame: %s",
                              toString(address_or_error.takeError()).c_str());
    return false;
  }
}

bool LLVMUserExpression::PrepareArgumentStruct(
    DiagnosticManager &diagnostic_manager, lldb::StackFrameSP &frame,
    lldb::addr_t &struct_address) {

  if (m_materialized_address == LLDB_INVALID_ADDRESS) {
    IRMemoryMap::AllocationPolicy policy =
        m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly
                        : IRMemoryMap::eAllocationPolicyMirror;

    const bool zero_memory = false;
    if (auto address_or_error = m_execution_unit_sp->Malloc(
            m_materializer_up->GetStructByteSize(),
            m_materializer_up->GetStructAlignment(),
            lldb::ePermissionsReadable | lldb::ePermissionsWritable, policy,
            zero_memory)) {
      m_materialized_address = *address_or_error;
    } else {
      diagnostic_manager.Printf(
          lldb::eSeverityError,
          "Couldn't allocate space for materialized struct: %s",
          toString(address_or_error.takeError()).c_str());
      return false;
    }
  }

  struct_address = m_materialized_address;

  Status materialize_error;

  m_dematerializer_sp = m_materializer_up->Materialize(
      frame, *m_execution_unit_sp, struct_address, materialize_error);

  if (!materialize_error.Success()) {
    diagnostic_manager.Printf(lldb::eSeverityError, "Couldn't materialize: %s",
                              materialize_error.AsCString());
    return false;
  }

  return true;
}
