//===-- FunctionCaller.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/FunctionCaller.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectList.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.h"

using namespace lldb_private;

char FunctionCaller::ID;

// FunctionCaller constructor
FunctionCaller::FunctionCaller(ExecutionContextScope &exe_scope,
                               const CompilerType &return_type,
                               const Address &functionAddress,
                               const ValueList &arg_value_list,
                               const char *name)
    : Expression(exe_scope), m_execution_unit_sp(), m_parser(),
      m_jit_module_wp(), m_name(name ? name : "<unknown>"),
      m_function_ptr(nullptr), m_function_addr(functionAddress),
      m_function_return_type(return_type),
      m_wrapper_function_name("__lldb_caller_function"),
      m_wrapper_struct_name("__lldb_caller_struct"), m_wrapper_args_addrs(),
      m_struct_valid(false), m_struct_size(0), m_return_size(0),
      m_return_offset(0), m_arg_values(arg_value_list), m_compiled(false),
      m_JITted(false) {
  m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
  // Can't make a FunctionCaller without a process.
  assert(m_jit_process_wp.lock());
}

// Destructor
FunctionCaller::~FunctionCaller() {
  lldb::ProcessSP process_sp(m_jit_process_wp.lock());
  if (process_sp) {
    lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock());
    if (jit_module_sp)
      process_sp->GetTarget().GetImages().Remove(jit_module_sp);
  }
}

bool FunctionCaller::WriteFunctionWrapper(
    ExecutionContext &exe_ctx, DiagnosticManager &diagnostic_manager) {
  Process *process = exe_ctx.GetProcessPtr();

  if (!process) {
    diagnostic_manager.Printf(lldb::eSeverityError, "no process.");
    return false;
  }
  
  lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());

  if (process != jit_process_sp.get()) {
    diagnostic_manager.Printf(lldb::eSeverityError,
                              "process does not match the stored process.");
    return false;
  }
    
  if (process->GetState() != lldb::eStateStopped) {
    diagnostic_manager.Printf(lldb::eSeverityError, "process is not stopped");
    return false;
  }

  if (!m_compiled) {
    diagnostic_manager.Printf(lldb::eSeverityError, "function not compiled");
    return false;
  }
  
  if (m_JITted)
    return true;

  bool can_interpret = false; // should stay that way

  Status jit_error(m_parser->PrepareForExecution(
      m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
      can_interpret, eExecutionPolicyAlways));

  if (!jit_error.Success()) {
    diagnostic_manager.Printf(lldb::eSeverityError,
                              "Error in PrepareForExecution: %s.",
                              jit_error.AsCString());
    return false;
  }

  if (m_parser->GetGenerateDebugInfo()) {
    lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());

    if (jit_module_sp) {
      ConstString const_func_name(FunctionName());
      FileSpec jit_file;
      jit_file.SetFilename(const_func_name);
      jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString());
      m_jit_module_wp = jit_module_sp;
      process->GetTarget().GetImages().Append(jit_module_sp,
                                              true /* notify */);
    }
  }
  if (process && m_jit_start_addr)
    m_jit_process_wp = process->shared_from_this();

  m_JITted = true;

  return true;
}

bool FunctionCaller::WriteFunctionArguments(
    ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref,
    DiagnosticManager &diagnostic_manager) {
  return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values,
                                diagnostic_manager);
}

// FIXME: Assure that the ValueList we were passed in is consistent with the one
// that defined this function.

bool FunctionCaller::WriteFunctionArguments(
    ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref,
    ValueList &arg_values, DiagnosticManager &diagnostic_manager) {
  // All the information to reconstruct the struct is provided by the
  // StructExtractor.
  if (!m_struct_valid) {
    diagnostic_manager.PutString(lldb::eSeverityError,
                                 "Argument information was not correctly "
                                 "parsed, so the function cannot be called.");
    return false;
  }

  Status error;
  lldb::ExpressionResults return_value = lldb::eExpressionSetupError;

  Process *process = exe_ctx.GetProcessPtr();

  if (process == nullptr)
    return return_value;

  lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());

  if (process != jit_process_sp.get())
    return false;

  if (args_addr_ref == LLDB_INVALID_ADDRESS) {
    args_addr_ref = process->AllocateMemory(
        m_struct_size, lldb::ePermissionsReadable | lldb::ePermissionsWritable,
        error);
    if (args_addr_ref == LLDB_INVALID_ADDRESS)
      return false;
    m_wrapper_args_addrs.push_back(args_addr_ref);
  } else {
    // Make sure this is an address that we've already handed out.
    if (find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(),
             args_addr_ref) == m_wrapper_args_addrs.end()) {
      return false;
    }
  }

  // TODO: verify fun_addr needs to be a callable address
  Scalar fun_addr(
      m_function_addr.GetCallableLoadAddress(exe_ctx.GetTargetPtr()));
  uint64_t first_offset = m_member_offsets[0];
  process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr,
                               process->GetAddressByteSize(), error);

  // FIXME: We will need to extend this for Variadic functions.

  Status value_error;

  size_t num_args = arg_values.GetSize();
  if (num_args != m_arg_values.GetSize()) {
    diagnostic_manager.Printf(
        lldb::eSeverityError,
        "Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "",
        (uint64_t)num_args, (uint64_t)m_arg_values.GetSize());
    return false;
  }

  for (size_t i = 0; i < num_args; i++) {
    // FIXME: We should sanity check sizes.

    uint64_t offset = m_member_offsets[i + 1]; // Clang sizes are in bytes.
    Value *arg_value = arg_values.GetValueAtIndex(i);

    // FIXME: For now just do scalars:

    // Special case: if it's a pointer, don't do anything (the ABI supports
    // passing cstrings)

    if (arg_value->GetValueType() == Value::ValueType::HostAddress &&
        arg_value->GetContextType() == Value::ContextType::Invalid &&
        arg_value->GetCompilerType().IsPointerType())
      continue;

    const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx);

    if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar,
                                      arg_scalar.GetByteSize(), error))
      return false;
  }

  return true;
}

bool FunctionCaller::InsertFunction(ExecutionContext &exe_ctx,
                                    lldb::addr_t &args_addr_ref,
                                    DiagnosticManager &diagnostic_manager) {
  // Since we might need to call allocate memory and maybe call code to make
  // the caller, we need to be stopped.
  Process *process = exe_ctx.GetProcessPtr();
  if (!process) {
    diagnostic_manager.PutString(lldb::eSeverityError, "no process");
    return false;
  }
  if (process->GetState() != lldb::eStateStopped) {
    diagnostic_manager.PutString(lldb::eSeverityError, "process running");
    return false;
  }
  if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0)
    return false;
  if (!WriteFunctionWrapper(exe_ctx, diagnostic_manager))
    return false;
  if (!WriteFunctionArguments(exe_ctx, args_addr_ref, diagnostic_manager))
    return false;

  Log *log = GetLog(LLDBLog::Step);
  LLDB_LOGF(log, "Call Address: 0x%" PRIx64 " Struct Address: 0x%" PRIx64 ".\n",
            m_jit_start_addr, args_addr_ref);

  return true;
}

lldb::ThreadPlanSP FunctionCaller::GetThreadPlanToCallFunction(
    ExecutionContext &exe_ctx, lldb::addr_t args_addr,
    const EvaluateExpressionOptions &options,
    DiagnosticManager &diagnostic_manager) {
  Log *log(GetLog(LLDBLog::Expressions | LLDBLog::Step));

  LLDB_LOGF(log,
            "-- [FunctionCaller::GetThreadPlanToCallFunction] Creating "
            "thread plan to call function \"%s\" --",
            m_name.c_str());

  // FIXME: Use the errors Stream for better error reporting.
  Thread *thread = exe_ctx.GetThreadPtr();
  if (thread == nullptr) {
    diagnostic_manager.PutString(
        lldb::eSeverityError, "Can't call a function without a valid thread.");
    return nullptr;
  }

  // Okay, now run the function:

  Address wrapper_address(m_jit_start_addr);

  lldb::addr_t args = {args_addr};

  lldb::ThreadPlanSP new_plan_sp(new ThreadPlanCallFunction(
      *thread, wrapper_address, CompilerType(), args, options));
  new_plan_sp->SetIsControllingPlan(true);
  new_plan_sp->SetOkayToDiscard(false);
  return new_plan_sp;
}

bool FunctionCaller::FetchFunctionResults(ExecutionContext &exe_ctx,
                                          lldb::addr_t args_addr,
                                          Value &ret_value) {
  // Read the return value - it is the last field in the struct:
  // FIXME: How does clang tell us there's no return value?  We need to handle
  // that case.
  // FIXME: Create our ThreadPlanCallFunction with the return CompilerType, and
  // then use GetReturnValueObject
  // to fetch the value.  That way we can fetch any values we need.

  Log *log(GetLog(LLDBLog::Expressions | LLDBLog::Step));

  LLDB_LOGF(log,
            "-- [FunctionCaller::FetchFunctionResults] Fetching function "
            "results for \"%s\"--",
            m_name.c_str());

  Process *process = exe_ctx.GetProcessPtr();

  if (process == nullptr)
    return false;

  lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());

  if (process != jit_process_sp.get())
    return false;

  Status error;
  ret_value.GetScalar() = process->ReadUnsignedIntegerFromMemory(
      args_addr + m_return_offset, m_return_size, 0, error);

  if (error.Fail())
    return false;

  ret_value.SetCompilerType(m_function_return_type);
  ret_value.SetValueType(Value::ValueType::Scalar);
  return true;
}

void FunctionCaller::DeallocateFunctionResults(ExecutionContext &exe_ctx,
                                               lldb::addr_t args_addr) {
  std::list<lldb::addr_t>::iterator pos;
  pos = std::find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(),
                  args_addr);
  if (pos != m_wrapper_args_addrs.end())
    m_wrapper_args_addrs.erase(pos);

  exe_ctx.GetProcessRef().DeallocateMemory(args_addr);
}

lldb::ExpressionResults FunctionCaller::ExecuteFunction(
    ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr,
    const EvaluateExpressionOptions &options,
    DiagnosticManager &diagnostic_manager, Value &results) {
  lldb::ExpressionResults return_value = lldb::eExpressionSetupError;

  // FunctionCaller::ExecuteFunction execution is always just to get the
  // result. Unless explicitly asked for, ignore breakpoints and unwind on
  // error.
  const bool enable_debugging =
      exe_ctx.GetTargetPtr() &&
      exe_ctx.GetTargetPtr()->GetDebugUtilityExpression();
  EvaluateExpressionOptions real_options = options;
  real_options.SetDebug(false); // This halts the expression for debugging.
  real_options.SetGenerateDebugInfo(enable_debugging);
  real_options.SetUnwindOnError(!enable_debugging);
  real_options.SetIgnoreBreakpoints(!enable_debugging);

  lldb::addr_t args_addr;

  if (args_addr_ptr != nullptr)
    args_addr = *args_addr_ptr;
  else
    args_addr = LLDB_INVALID_ADDRESS;

  if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0)
    return lldb::eExpressionSetupError;

  if (args_addr == LLDB_INVALID_ADDRESS) {
    if (!InsertFunction(exe_ctx, args_addr, diagnostic_manager))
      return lldb::eExpressionSetupError;
  }

  Log *log(GetLog(LLDBLog::Expressions | LLDBLog::Step));

  LLDB_LOGF(log,
            "== [FunctionCaller::ExecuteFunction] Executing function \"%s\" ==",
            m_name.c_str());

  lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction(
      exe_ctx, args_addr, real_options, diagnostic_manager);
  if (!call_plan_sp)
    return lldb::eExpressionSetupError;

  // We need to make sure we record the fact that we are running an expression
  // here otherwise this fact will fail to be recorded when fetching an
  // Objective-C object description
  if (exe_ctx.GetProcessPtr())
    exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);

  return_value = exe_ctx.GetProcessRef().RunThreadPlan(
      exe_ctx, call_plan_sp, real_options, diagnostic_manager);

  if (log) {
    if (return_value != lldb::eExpressionCompleted) {
      LLDB_LOGF(log,
                "== [FunctionCaller::ExecuteFunction] Execution of \"%s\" "
                "completed abnormally: %s ==",
                m_name.c_str(),
                Process::ExecutionResultAsCString(return_value));
    } else {
      LLDB_LOGF(log,
                "== [FunctionCaller::ExecuteFunction] Execution of \"%s\" "
                "completed normally ==",
                m_name.c_str());
    }
  }

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

  if (args_addr_ptr != nullptr)
    *args_addr_ptr = args_addr;

  if (return_value != lldb::eExpressionCompleted)
    return return_value;

  FetchFunctionResults(exe_ctx, args_addr, results);

  if (args_addr_ptr == nullptr)
    DeallocateFunctionResults(exe_ctx, args_addr);

  return lldb::eExpressionCompleted;
}
