//===-- 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/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) {
  // 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;

  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);

    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::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 (FinalizeJITExecution(diagnostic_manager, exe_ctx, result,
                           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)
    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;
  }

  if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) {
    if (m_materialized_address == LLDB_INVALID_ADDRESS) {
      Status alloc_error;

      IRMemoryMap::AllocationPolicy policy =
          m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly
                          : IRMemoryMap::eAllocationPolicyMirror;

      const bool zero_memory = false;

      m_materialized_address = m_execution_unit_sp->Malloc(
          m_materializer_up->GetStructByteSize(),
          m_materializer_up->GetStructAlignment(),
          lldb::ePermissionsReadable | lldb::ePermissionsWritable, policy,
          zero_memory, alloc_error);

      if (!alloc_error.Success()) {
        diagnostic_manager.Printf(
            lldb::eSeverityError,
            "Couldn't allocate space for materialized struct: %s",
            alloc_error.AsCString());
        return false;
      }
    }

    struct_address = m_materialized_address;

    if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS) {
      Status alloc_error;

      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;

      m_stack_frame_bottom = m_execution_unit_sp->Malloc(
          stack_frame_size, 8,
          lldb::ePermissionsReadable | lldb::ePermissionsWritable,
          IRMemoryMap::eAllocationPolicyHostOnly, zero_memory, alloc_error);

      m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;

      if (!alloc_error.Success()) {
        diagnostic_manager.Printf(
            lldb::eSeverityError,
            "Couldn't allocate space for the stack frame: %s",
            alloc_error.AsCString());
        return false;
      }
    }

    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;
}

