1314564Sdim//===-- UtilityFunction.cpp -------------------------------------*- C++ -*-===//
2292932Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6292932Sdim//
7292932Sdim//===----------------------------------------------------------------------===//
8292932Sdim
9360784Sdim#include "lldb/Host/Config.h"
10360784Sdim
11292932Sdim#include <stdio.h>
12292932Sdim#if HAVE_SYS_TYPES_H
13314564Sdim#include <sys/types.h>
14292932Sdim#endif
15292932Sdim
16292932Sdim
17292932Sdim#include "lldb/Core/Module.h"
18292932Sdim#include "lldb/Core/StreamFile.h"
19309124Sdim#include "lldb/Expression/DiagnosticManager.h"
20292932Sdim#include "lldb/Expression/FunctionCaller.h"
21309124Sdim#include "lldb/Expression/IRExecutionUnit.h"
22292932Sdim#include "lldb/Expression/UtilityFunction.h"
23292932Sdim#include "lldb/Host/Host.h"
24292932Sdim#include "lldb/Target/ExecutionContext.h"
25292932Sdim#include "lldb/Target/Process.h"
26292932Sdim#include "lldb/Target/Target.h"
27321369Sdim#include "lldb/Utility/ConstString.h"
28321369Sdim#include "lldb/Utility/Log.h"
29321369Sdim#include "lldb/Utility/Stream.h"
30292932Sdim
31292932Sdimusing namespace lldb_private;
32292932Sdimusing namespace lldb;
33292932Sdim
34360784Sdimchar UtilityFunction::ID;
35360784Sdim
36292932Sdim/// Constructor
37292932Sdim///
38353358Sdim/// \param[in] text
39292932Sdim///     The text of the function.  Must be a full translation unit.
40292932Sdim///
41353358Sdim/// \param[in] name
42292932Sdim///     The name of the function, as used in the text.
43314564SdimUtilityFunction::UtilityFunction(ExecutionContextScope &exe_scope,
44360784Sdim                                 const char *text, const char *name)
45360784Sdim    : Expression(exe_scope), m_execution_unit_sp(), m_jit_module_wp(),
46360784Sdim      m_function_text(), m_function_name(name) {}
47292932Sdim
48314564SdimUtilityFunction::~UtilityFunction() {
49314564Sdim  lldb::ProcessSP process_sp(m_jit_process_wp.lock());
50314564Sdim  if (process_sp) {
51314564Sdim    lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock());
52314564Sdim    if (jit_module_sp)
53314564Sdim      process_sp->GetTarget().GetImages().Remove(jit_module_sp);
54314564Sdim  }
55292932Sdim}
56292932Sdim
57314564Sdim// FIXME: We should check that every time this is called it is called with the
58314564Sdim// same return type & arguments...
59292932Sdim
60314564SdimFunctionCaller *UtilityFunction::MakeFunctionCaller(
61314564Sdim    const CompilerType &return_type, const ValueList &arg_value_list,
62321369Sdim    lldb::ThreadSP thread_to_use_sp, Status &error) {
63314564Sdim  if (m_caller_up)
64314564Sdim    return m_caller_up.get();
65309124Sdim
66314564Sdim  ProcessSP process_sp = m_jit_process_wp.lock();
67314564Sdim  if (!process_sp) {
68314564Sdim    error.SetErrorString("Can't make a function caller without a process.");
69314564Sdim    return nullptr;
70314564Sdim  }
71309124Sdim
72314564Sdim  Address impl_code_address;
73314564Sdim  impl_code_address.SetOffset(StartAddress());
74314564Sdim  std::string name(m_function_name);
75314564Sdim  name.append("-caller");
76309124Sdim
77314564Sdim  m_caller_up.reset(process_sp->GetTarget().GetFunctionCallerForLanguage(
78314564Sdim      Language(), return_type, impl_code_address, arg_value_list, name.c_str(),
79314564Sdim      error));
80314564Sdim  if (error.Fail()) {
81314564Sdim
82314564Sdim    return nullptr;
83314564Sdim  }
84314564Sdim  if (m_caller_up) {
85314564Sdim    DiagnosticManager diagnostics;
86314564Sdim
87314564Sdim    unsigned num_errors =
88314564Sdim        m_caller_up->CompileFunction(thread_to_use_sp, diagnostics);
89314564Sdim    if (num_errors) {
90314564Sdim      error.SetErrorStringWithFormat(
91314564Sdim          "Error compiling %s caller function: \"%s\".",
92314564Sdim          m_function_name.c_str(), diagnostics.GetString().c_str());
93314564Sdim      m_caller_up.reset();
94314564Sdim      return nullptr;
95292932Sdim    }
96314564Sdim
97314564Sdim    diagnostics.Clear();
98314564Sdim    ExecutionContext exe_ctx(process_sp);
99314564Sdim
100314564Sdim    if (!m_caller_up->WriteFunctionWrapper(exe_ctx, diagnostics)) {
101314564Sdim      error.SetErrorStringWithFormat(
102314564Sdim          "Error inserting caller function for %s: \"%s\".",
103314564Sdim          m_function_name.c_str(), diagnostics.GetString().c_str());
104314564Sdim      m_caller_up.reset();
105314564Sdim      return nullptr;
106314564Sdim    }
107314564Sdim  }
108314564Sdim  return m_caller_up.get();
109292932Sdim}
110