UtilityFunction.cpp revision 314564
1314564Sdim//===-- UtilityFunction.cpp -------------------------------------*- C++ -*-===//
2292932Sdim//
3292932Sdim//                     The LLVM Compiler Infrastructure
4292932Sdim//
5292932Sdim// This file is distributed under the University of Illinois Open Source
6292932Sdim// License. See LICENSE.TXT for details.
7292932Sdim//
8292932Sdim//===----------------------------------------------------------------------===//
9292932Sdim
10292932Sdim// C Includes
11292932Sdim#include <stdio.h>
12292932Sdim#if HAVE_SYS_TYPES_H
13314564Sdim#include <sys/types.h>
14292932Sdim#endif
15292932Sdim
16292932Sdim// C++ Includes
17292932Sdim
18292932Sdim#include "lldb/Core/ConstString.h"
19292932Sdim#include "lldb/Core/Log.h"
20292932Sdim#include "lldb/Core/Module.h"
21292932Sdim#include "lldb/Core/Stream.h"
22292932Sdim#include "lldb/Core/StreamFile.h"
23309124Sdim#include "lldb/Expression/DiagnosticManager.h"
24309124Sdim#include "lldb/Expression/ExpressionSourceCode.h"
25292932Sdim#include "lldb/Expression/FunctionCaller.h"
26309124Sdim#include "lldb/Expression/IRExecutionUnit.h"
27292932Sdim#include "lldb/Expression/UtilityFunction.h"
28292932Sdim#include "lldb/Host/Host.h"
29292932Sdim#include "lldb/Target/ExecutionContext.h"
30292932Sdim#include "lldb/Target/Process.h"
31292932Sdim#include "lldb/Target/Target.h"
32292932Sdim
33292932Sdimusing namespace lldb_private;
34292932Sdimusing namespace lldb;
35292932Sdim
36292932Sdim//------------------------------------------------------------------
37292932Sdim/// Constructor
38292932Sdim///
39292932Sdim/// @param[in] text
40292932Sdim///     The text of the function.  Must be a full translation unit.
41292932Sdim///
42292932Sdim/// @param[in] name
43292932Sdim///     The name of the function, as used in the text.
44292932Sdim//------------------------------------------------------------------
45314564SdimUtilityFunction::UtilityFunction(ExecutionContextScope &exe_scope,
46314564Sdim                                 const char *text, const char *name)
47314564Sdim    : Expression(exe_scope), m_execution_unit_sp(), m_jit_module_wp(),
48314564Sdim      m_function_text(ExpressionSourceCode::g_expression_prefix),
49314564Sdim      m_function_name(name) {
50314564Sdim  if (text && text[0])
51314564Sdim    m_function_text.append(text);
52292932Sdim}
53292932Sdim
54314564SdimUtilityFunction::~UtilityFunction() {
55314564Sdim  lldb::ProcessSP process_sp(m_jit_process_wp.lock());
56314564Sdim  if (process_sp) {
57314564Sdim    lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock());
58314564Sdim    if (jit_module_sp)
59314564Sdim      process_sp->GetTarget().GetImages().Remove(jit_module_sp);
60314564Sdim  }
61292932Sdim}
62292932Sdim
63314564Sdim// FIXME: We should check that every time this is called it is called with the
64314564Sdim// same return type & arguments...
65292932Sdim
66314564SdimFunctionCaller *UtilityFunction::MakeFunctionCaller(
67314564Sdim    const CompilerType &return_type, const ValueList &arg_value_list,
68314564Sdim    lldb::ThreadSP thread_to_use_sp, Error &error) {
69314564Sdim  if (m_caller_up)
70314564Sdim    return m_caller_up.get();
71309124Sdim
72314564Sdim  ProcessSP process_sp = m_jit_process_wp.lock();
73314564Sdim  if (!process_sp) {
74314564Sdim    error.SetErrorString("Can't make a function caller without a process.");
75314564Sdim    return nullptr;
76314564Sdim  }
77309124Sdim
78314564Sdim  Address impl_code_address;
79314564Sdim  impl_code_address.SetOffset(StartAddress());
80314564Sdim  std::string name(m_function_name);
81314564Sdim  name.append("-caller");
82309124Sdim
83314564Sdim  m_caller_up.reset(process_sp->GetTarget().GetFunctionCallerForLanguage(
84314564Sdim      Language(), return_type, impl_code_address, arg_value_list, name.c_str(),
85314564Sdim      error));
86314564Sdim  if (error.Fail()) {
87314564Sdim
88314564Sdim    return nullptr;
89314564Sdim  }
90314564Sdim  if (m_caller_up) {
91314564Sdim    DiagnosticManager diagnostics;
92314564Sdim
93314564Sdim    unsigned num_errors =
94314564Sdim        m_caller_up->CompileFunction(thread_to_use_sp, diagnostics);
95314564Sdim    if (num_errors) {
96314564Sdim      error.SetErrorStringWithFormat(
97314564Sdim          "Error compiling %s caller function: \"%s\".",
98314564Sdim          m_function_name.c_str(), diagnostics.GetString().c_str());
99314564Sdim      m_caller_up.reset();
100314564Sdim      return nullptr;
101292932Sdim    }
102314564Sdim
103314564Sdim    diagnostics.Clear();
104314564Sdim    ExecutionContext exe_ctx(process_sp);
105314564Sdim
106314564Sdim    if (!m_caller_up->WriteFunctionWrapper(exe_ctx, diagnostics)) {
107314564Sdim      error.SetErrorStringWithFormat(
108314564Sdim          "Error inserting caller function for %s: \"%s\".",
109314564Sdim          m_function_name.c_str(), diagnostics.GetString().c_str());
110314564Sdim      m_caller_up.reset();
111314564Sdim      return nullptr;
112314564Sdim    }
113314564Sdim  }
114314564Sdim  return m_caller_up.get();
115292932Sdim}
116