1151c032cSJim Ingham //===-- FunctionCaller.cpp ---------------------------------------*- C++ -*-===//
2151c032cSJim Ingham //
3151c032cSJim Ingham //                     The LLVM Compiler Infrastructure
4151c032cSJim Ingham //
5151c032cSJim Ingham // This file is distributed under the University of Illinois Open Source
6151c032cSJim Ingham // License. See LICENSE.TXT for details.
7151c032cSJim Ingham //
8151c032cSJim Ingham //===----------------------------------------------------------------------===//
9151c032cSJim Ingham 
10151c032cSJim Ingham 
11151c032cSJim Ingham // C Includes
12151c032cSJim Ingham // C++ Includes
13151c032cSJim Ingham // Other libraries and framework includes
14151c032cSJim Ingham 
15151c032cSJim Ingham // Project includes
16579e70c9SSean Callanan #include "lldb/Expression/FunctionCaller.h"
17151c032cSJim Ingham #include "lldb/Core/DataExtractor.h"
18151c032cSJim Ingham #include "lldb/Core/Log.h"
19151c032cSJim Ingham #include "lldb/Core/Module.h"
20151c032cSJim Ingham #include "lldb/Core/State.h"
21151c032cSJim Ingham #include "lldb/Core/ValueObject.h"
22151c032cSJim Ingham #include "lldb/Core/ValueObjectList.h"
23579e70c9SSean Callanan #include "lldb/Expression/DiagnosticManager.h"
24151c032cSJim Ingham #include "lldb/Expression/IRExecutionUnit.h"
25151c032cSJim Ingham #include "lldb/Interpreter/CommandReturnObject.h"
26151c032cSJim Ingham #include "lldb/Symbol/Function.h"
27151c032cSJim Ingham #include "lldb/Symbol/Type.h"
28151c032cSJim Ingham #include "lldb/Target/ExecutionContext.h"
29151c032cSJim Ingham #include "lldb/Target/Process.h"
30151c032cSJim Ingham #include "lldb/Target/RegisterContext.h"
31151c032cSJim Ingham #include "lldb/Target/Target.h"
32151c032cSJim Ingham #include "lldb/Target/Thread.h"
33151c032cSJim Ingham #include "lldb/Target/ThreadPlan.h"
34151c032cSJim Ingham #include "lldb/Target/ThreadPlanCallFunction.h"
35151c032cSJim Ingham 
36151c032cSJim Ingham using namespace lldb_private;
37151c032cSJim Ingham 
38151c032cSJim Ingham //----------------------------------------------------------------------
39151c032cSJim Ingham // FunctionCaller constructor
40151c032cSJim Ingham //----------------------------------------------------------------------
41151c032cSJim Ingham FunctionCaller::FunctionCaller
42151c032cSJim Ingham (
43151c032cSJim Ingham     ExecutionContextScope &exe_scope,
44151c032cSJim Ingham     const CompilerType &return_type,
45151c032cSJim Ingham     const Address& functionAddress,
46151c032cSJim Ingham     const ValueList &arg_value_list,
47151c032cSJim Ingham     const char *name
48151c032cSJim Ingham ) :
49151c032cSJim Ingham     Expression (exe_scope),
50151c032cSJim Ingham     m_execution_unit_sp(),
51151c032cSJim Ingham     m_parser(),
52151c032cSJim Ingham     m_jit_module_wp(),
53151c032cSJim Ingham     m_name (name ? name : "<unknown>"),
54151c032cSJim Ingham     m_function_ptr (NULL),
55151c032cSJim Ingham     m_function_addr (functionAddress),
56151c032cSJim Ingham     m_function_return_type(return_type),
57151c032cSJim Ingham     m_wrapper_function_name ("__lldb_caller_function"),
58151c032cSJim Ingham     m_wrapper_struct_name ("__lldb_caller_struct"),
59151c032cSJim Ingham     m_wrapper_args_addrs (),
60151c032cSJim Ingham     m_arg_values (arg_value_list),
61151c032cSJim Ingham     m_compiled (false),
62151c032cSJim Ingham     m_JITted (false)
63151c032cSJim Ingham {
64151c032cSJim Ingham     m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
65151c032cSJim Ingham     // Can't make a FunctionCaller without a process.
66151c032cSJim Ingham     assert (m_jit_process_wp.lock());
67151c032cSJim Ingham }
68151c032cSJim Ingham 
69151c032cSJim Ingham //----------------------------------------------------------------------
70151c032cSJim Ingham // Destructor
71151c032cSJim Ingham //----------------------------------------------------------------------
72151c032cSJim Ingham FunctionCaller::~FunctionCaller()
73151c032cSJim Ingham {
74151c032cSJim Ingham     lldb::ProcessSP process_sp (m_jit_process_wp.lock());
75151c032cSJim Ingham     if (process_sp)
76151c032cSJim Ingham     {
77151c032cSJim Ingham         lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
78151c032cSJim Ingham         if (jit_module_sp)
79151c032cSJim Ingham             process_sp->GetTarget().GetImages().Remove(jit_module_sp);
80151c032cSJim Ingham     }
81151c032cSJim Ingham }
82151c032cSJim Ingham 
83151c032cSJim Ingham bool
84579e70c9SSean Callanan FunctionCaller::WriteFunctionWrapper(ExecutionContext &exe_ctx, DiagnosticManager &diagnostic_manager)
85151c032cSJim Ingham {
86151c032cSJim Ingham     Process *process = exe_ctx.GetProcessPtr();
87151c032cSJim Ingham 
88151c032cSJim Ingham     if (!process)
89151c032cSJim Ingham         return false;
90151c032cSJim Ingham 
91151c032cSJim Ingham     lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
92151c032cSJim Ingham 
93151c032cSJim Ingham     if (process != jit_process_sp.get())
94151c032cSJim Ingham         return false;
95151c032cSJim Ingham 
96151c032cSJim Ingham     if (!m_compiled)
97151c032cSJim Ingham         return false;
98151c032cSJim Ingham 
99151c032cSJim Ingham     if (m_JITted)
100151c032cSJim Ingham         return true;
101151c032cSJim Ingham 
102151c032cSJim Ingham     bool can_interpret = false; // should stay that way
103151c032cSJim Ingham 
104151c032cSJim Ingham     Error jit_error (m_parser->PrepareForExecution (m_jit_start_addr,
105151c032cSJim Ingham                                                     m_jit_end_addr,
106151c032cSJim Ingham                                                     m_execution_unit_sp,
107151c032cSJim Ingham                                                     exe_ctx,
108151c032cSJim Ingham                                                     can_interpret,
109151c032cSJim Ingham                                                     eExecutionPolicyAlways));
110151c032cSJim Ingham 
111151c032cSJim Ingham     if (!jit_error.Success())
112151c032cSJim Ingham         return false;
113151c032cSJim Ingham 
114151c032cSJim Ingham     if (m_parser->GetGenerateDebugInfo())
115151c032cSJim Ingham     {
116151c032cSJim Ingham         lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
117151c032cSJim Ingham 
118151c032cSJim Ingham         if (jit_module_sp)
119151c032cSJim Ingham         {
120151c032cSJim Ingham             ConstString const_func_name(FunctionName());
121151c032cSJim Ingham             FileSpec jit_file;
122151c032cSJim Ingham             jit_file.GetFilename() = const_func_name;
123151c032cSJim Ingham             jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
124151c032cSJim Ingham             m_jit_module_wp = jit_module_sp;
125151c032cSJim Ingham             process->GetTarget().GetImages().Append(jit_module_sp);
126151c032cSJim Ingham         }
127151c032cSJim Ingham     }
128151c032cSJim Ingham     if (process && m_jit_start_addr)
129151c032cSJim Ingham         m_jit_process_wp = process->shared_from_this();
130151c032cSJim Ingham 
131151c032cSJim Ingham     m_JITted = true;
132151c032cSJim Ingham 
133151c032cSJim Ingham     return true;
134151c032cSJim Ingham }
135151c032cSJim Ingham 
136151c032cSJim Ingham bool
137579e70c9SSean Callanan FunctionCaller::WriteFunctionArguments(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref,
138579e70c9SSean Callanan                                        DiagnosticManager &diagnostic_manager)
139151c032cSJim Ingham {
140579e70c9SSean Callanan     return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values, diagnostic_manager);
141151c032cSJim Ingham }
142151c032cSJim Ingham 
143151c032cSJim Ingham // FIXME: Assure that the ValueList we were passed in is consistent with the one that defined this function.
144151c032cSJim Ingham 
145151c032cSJim Ingham bool
146579e70c9SSean Callanan FunctionCaller::WriteFunctionArguments(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, ValueList &arg_values,
147579e70c9SSean Callanan                                        DiagnosticManager &diagnostic_manager)
148151c032cSJim Ingham {
149151c032cSJim Ingham     // All the information to reconstruct the struct is provided by the
150151c032cSJim Ingham     // StructExtractor.
151151c032cSJim Ingham     if (!m_struct_valid)
152151c032cSJim Ingham     {
153579e70c9SSean Callanan         diagnostic_manager.PutCString(
154579e70c9SSean Callanan             eDiagnosticSeverityError,
155579e70c9SSean Callanan             "Argument information was not correctly parsed, so the function cannot be called.");
156151c032cSJim Ingham         return false;
157151c032cSJim Ingham     }
158151c032cSJim Ingham 
159151c032cSJim Ingham     Error error;
160151c032cSJim Ingham     lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
161151c032cSJim Ingham 
162151c032cSJim Ingham     Process *process = exe_ctx.GetProcessPtr();
163151c032cSJim Ingham 
164151c032cSJim Ingham     if (process == NULL)
165151c032cSJim Ingham         return return_value;
166151c032cSJim Ingham 
167151c032cSJim Ingham     lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
168151c032cSJim Ingham 
169151c032cSJim Ingham     if (process != jit_process_sp.get())
170151c032cSJim Ingham         return false;
171151c032cSJim Ingham 
172151c032cSJim Ingham     if (args_addr_ref == LLDB_INVALID_ADDRESS)
173151c032cSJim Ingham     {
174151c032cSJim Ingham         args_addr_ref = process->AllocateMemory(m_struct_size, lldb::ePermissionsReadable|lldb::ePermissionsWritable, error);
175151c032cSJim Ingham         if (args_addr_ref == LLDB_INVALID_ADDRESS)
176151c032cSJim Ingham             return false;
177151c032cSJim Ingham         m_wrapper_args_addrs.push_back (args_addr_ref);
178151c032cSJim Ingham     }
179151c032cSJim Ingham     else
180151c032cSJim Ingham     {
181151c032cSJim Ingham         // Make sure this is an address that we've already handed out.
182151c032cSJim Ingham         if (find (m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr_ref) == m_wrapper_args_addrs.end())
183151c032cSJim Ingham         {
184151c032cSJim Ingham             return false;
185151c032cSJim Ingham         }
186151c032cSJim Ingham     }
187151c032cSJim Ingham 
188151c032cSJim Ingham     // TODO: verify fun_addr needs to be a callable address
189151c032cSJim Ingham     Scalar fun_addr (m_function_addr.GetCallableLoadAddress(exe_ctx.GetTargetPtr()));
190151c032cSJim Ingham     uint64_t first_offset = m_member_offsets[0];
191151c032cSJim Ingham     process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error);
192151c032cSJim Ingham 
193151c032cSJim Ingham     // FIXME: We will need to extend this for Variadic functions.
194151c032cSJim Ingham 
195151c032cSJim Ingham     Error value_error;
196151c032cSJim Ingham 
197151c032cSJim Ingham     size_t num_args = arg_values.GetSize();
198151c032cSJim Ingham     if (num_args != m_arg_values.GetSize())
199151c032cSJim Ingham     {
200579e70c9SSean Callanan         diagnostic_manager.Printf(eDiagnosticSeverityError,
201579e70c9SSean Callanan                                   "Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "",
202579e70c9SSean Callanan                                   (uint64_t)num_args, (uint64_t)m_arg_values.GetSize());
203151c032cSJim Ingham         return false;
204151c032cSJim Ingham     }
205151c032cSJim Ingham 
206151c032cSJim Ingham     for (size_t i = 0; i < num_args; i++)
207151c032cSJim Ingham     {
208151c032cSJim Ingham         // FIXME: We should sanity check sizes.
209151c032cSJim Ingham 
210151c032cSJim Ingham         uint64_t offset = m_member_offsets[i+1]; // Clang sizes are in bytes.
211151c032cSJim Ingham         Value *arg_value = arg_values.GetValueAtIndex(i);
212151c032cSJim Ingham 
213151c032cSJim Ingham         // FIXME: For now just do scalars:
214151c032cSJim Ingham 
215151c032cSJim Ingham         // Special case: if it's a pointer, don't do anything (the ABI supports passing cstrings)
216151c032cSJim Ingham 
217151c032cSJim Ingham         if (arg_value->GetValueType() == Value::eValueTypeHostAddress &&
218151c032cSJim Ingham             arg_value->GetContextType() == Value::eContextTypeInvalid &&
219151c032cSJim Ingham             arg_value->GetCompilerType().IsPointerType())
220151c032cSJim Ingham             continue;
221151c032cSJim Ingham 
222151c032cSJim Ingham         const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx);
223151c032cSJim Ingham 
224151c032cSJim Ingham         if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar, arg_scalar.GetByteSize(), error))
225151c032cSJim Ingham             return false;
226151c032cSJim Ingham     }
227151c032cSJim Ingham 
228151c032cSJim Ingham     return true;
229151c032cSJim Ingham }
230151c032cSJim Ingham 
231151c032cSJim Ingham bool
232579e70c9SSean Callanan FunctionCaller::InsertFunction(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref,
233579e70c9SSean Callanan                                DiagnosticManager &diagnostic_manager)
234151c032cSJim Ingham {
235*6896b355SJim Ingham     if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0)
236151c032cSJim Ingham         return false;
237579e70c9SSean Callanan     if (!WriteFunctionWrapper(exe_ctx, diagnostic_manager))
238151c032cSJim Ingham         return false;
239579e70c9SSean Callanan     if (!WriteFunctionArguments(exe_ctx, args_addr_ref, diagnostic_manager))
240151c032cSJim Ingham         return false;
241151c032cSJim Ingham 
242151c032cSJim Ingham     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
243151c032cSJim Ingham     if (log)
244151c032cSJim Ingham         log->Printf ("Call Address: 0x%" PRIx64 " Struct Address: 0x%" PRIx64 ".\n", m_jit_start_addr, args_addr_ref);
245151c032cSJim Ingham 
246151c032cSJim Ingham     return true;
247151c032cSJim Ingham }
248151c032cSJim Ingham 
249151c032cSJim Ingham lldb::ThreadPlanSP
250579e70c9SSean Callanan FunctionCaller::GetThreadPlanToCallFunction(ExecutionContext &exe_ctx, lldb::addr_t args_addr,
251151c032cSJim Ingham                                             const EvaluateExpressionOptions &options,
252579e70c9SSean Callanan                                             DiagnosticManager &diagnostic_manager)
253151c032cSJim Ingham {
254151c032cSJim Ingham     Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
255151c032cSJim Ingham 
256151c032cSJim Ingham     if (log)
257151c032cSJim Ingham         log->Printf("-- [FunctionCaller::GetThreadPlanToCallFunction] Creating thread plan to call function \"%s\" --", m_name.c_str());
258151c032cSJim Ingham 
259151c032cSJim Ingham     // FIXME: Use the errors Stream for better error reporting.
260151c032cSJim Ingham     Thread *thread = exe_ctx.GetThreadPtr();
261151c032cSJim Ingham     if (thread == NULL)
262151c032cSJim Ingham     {
263579e70c9SSean Callanan         diagnostic_manager.PutCString(eDiagnosticSeverityError, "Can't call a function without a valid thread.");
264151c032cSJim Ingham         return NULL;
265151c032cSJim Ingham     }
266151c032cSJim Ingham 
267151c032cSJim Ingham     // Okay, now run the function:
268151c032cSJim Ingham 
269151c032cSJim Ingham     Address wrapper_address (m_jit_start_addr);
270151c032cSJim Ingham 
271151c032cSJim Ingham     lldb::addr_t args = { args_addr };
272151c032cSJim Ingham 
273151c032cSJim Ingham     lldb::ThreadPlanSP new_plan_sp (new ThreadPlanCallFunction (*thread,
274151c032cSJim Ingham                                                        wrapper_address,
275151c032cSJim Ingham                                                        CompilerType(),
276151c032cSJim Ingham                                                        args,
277151c032cSJim Ingham                                                        options));
278151c032cSJim Ingham     new_plan_sp->SetIsMasterPlan(true);
279151c032cSJim Ingham     new_plan_sp->SetOkayToDiscard (false);
280151c032cSJim Ingham     return new_plan_sp;
281151c032cSJim Ingham }
282151c032cSJim Ingham 
283151c032cSJim Ingham bool
284151c032cSJim Ingham FunctionCaller::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value)
285151c032cSJim Ingham {
286151c032cSJim Ingham     // Read the return value - it is the last field in the struct:
287151c032cSJim Ingham     // FIXME: How does clang tell us there's no return value?  We need to handle that case.
288151c032cSJim Ingham     // FIXME: Create our ThreadPlanCallFunction with the return CompilerType, and then use GetReturnValueObject
289151c032cSJim Ingham     // to fetch the value.  That way we can fetch any values we need.
290151c032cSJim Ingham 
291151c032cSJim Ingham     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
292151c032cSJim Ingham 
293151c032cSJim Ingham     if (log)
294151c032cSJim Ingham         log->Printf("-- [FunctionCaller::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str());
295151c032cSJim Ingham 
296151c032cSJim Ingham     Process *process = exe_ctx.GetProcessPtr();
297151c032cSJim Ingham 
298151c032cSJim Ingham     if (process == NULL)
299151c032cSJim Ingham         return false;
300151c032cSJim Ingham 
301151c032cSJim Ingham     lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
302151c032cSJim Ingham 
303151c032cSJim Ingham     if (process != jit_process_sp.get())
304151c032cSJim Ingham         return false;
305151c032cSJim Ingham 
306151c032cSJim Ingham     Error error;
307151c032cSJim Ingham     ret_value.GetScalar() = process->ReadUnsignedIntegerFromMemory (args_addr + m_return_offset, m_return_size, 0, error);
308151c032cSJim Ingham 
309151c032cSJim Ingham     if (error.Fail())
310151c032cSJim Ingham         return false;
311151c032cSJim Ingham 
312151c032cSJim Ingham     ret_value.SetCompilerType(m_function_return_type);
313151c032cSJim Ingham     ret_value.SetValueType(Value::eValueTypeScalar);
314151c032cSJim Ingham     return true;
315151c032cSJim Ingham }
316151c032cSJim Ingham 
317151c032cSJim Ingham void
318151c032cSJim Ingham FunctionCaller::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr)
319151c032cSJim Ingham {
320151c032cSJim Ingham     std::list<lldb::addr_t>::iterator pos;
321151c032cSJim Ingham     pos = std::find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr);
322151c032cSJim Ingham     if (pos != m_wrapper_args_addrs.end())
323151c032cSJim Ingham         m_wrapper_args_addrs.erase(pos);
324151c032cSJim Ingham 
325151c032cSJim Ingham     exe_ctx.GetProcessRef().DeallocateMemory(args_addr);
326151c032cSJim Ingham }
327151c032cSJim Ingham 
328151c032cSJim Ingham lldb::ExpressionResults
329579e70c9SSean Callanan FunctionCaller::ExecuteFunction(ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr,
330579e70c9SSean Callanan                                 const EvaluateExpressionOptions &options, DiagnosticManager &diagnostic_manager,
331151c032cSJim Ingham                                 Value &results)
332151c032cSJim Ingham {
333151c032cSJim Ingham     lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
334151c032cSJim Ingham 
335151c032cSJim Ingham     // FunctionCaller::ExecuteFunction execution is always just to get the result.  Do make sure we ignore
336151c032cSJim Ingham     // breakpoints, unwind on error, and don't try to debug it.
337151c032cSJim Ingham     EvaluateExpressionOptions real_options = options;
338151c032cSJim Ingham     real_options.SetDebug(false);
339151c032cSJim Ingham     real_options.SetUnwindOnError(true);
340151c032cSJim Ingham     real_options.SetIgnoreBreakpoints(true);
341151c032cSJim Ingham 
342151c032cSJim Ingham     lldb::addr_t args_addr;
343151c032cSJim Ingham 
344151c032cSJim Ingham     if (args_addr_ptr != NULL)
345151c032cSJim Ingham         args_addr = *args_addr_ptr;
346151c032cSJim Ingham     else
347151c032cSJim Ingham         args_addr = LLDB_INVALID_ADDRESS;
348151c032cSJim Ingham 
349*6896b355SJim Ingham     if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0)
350151c032cSJim Ingham         return lldb::eExpressionSetupError;
351151c032cSJim Ingham 
352151c032cSJim Ingham     if (args_addr == LLDB_INVALID_ADDRESS)
353151c032cSJim Ingham     {
354579e70c9SSean Callanan         if (!InsertFunction(exe_ctx, args_addr, diagnostic_manager))
355151c032cSJim Ingham             return lldb::eExpressionSetupError;
356151c032cSJim Ingham     }
357151c032cSJim Ingham 
358151c032cSJim Ingham     Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
359151c032cSJim Ingham 
360151c032cSJim Ingham     if (log)
361151c032cSJim Ingham         log->Printf("== [FunctionCaller::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str());
362151c032cSJim Ingham 
363579e70c9SSean Callanan     lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction(exe_ctx, args_addr, real_options, diagnostic_manager);
364151c032cSJim Ingham     if (!call_plan_sp)
365151c032cSJim Ingham         return lldb::eExpressionSetupError;
366151c032cSJim Ingham 
367151c032cSJim Ingham     // We need to make sure we record the fact that we are running an expression here
368151c032cSJim Ingham     // otherwise this fact will fail to be recorded when fetching an Objective-C object description
369151c032cSJim Ingham     if (exe_ctx.GetProcessPtr())
370151c032cSJim Ingham         exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
371151c032cSJim Ingham 
372579e70c9SSean Callanan     return_value = exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, real_options, diagnostic_manager);
373151c032cSJim Ingham 
374151c032cSJim Ingham     if (log)
375151c032cSJim Ingham     {
376151c032cSJim Ingham         if (return_value != lldb::eExpressionCompleted)
377151c032cSJim Ingham         {
378151c032cSJim Ingham             log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str());
379151c032cSJim Ingham         }
380151c032cSJim Ingham         else
381151c032cSJim Ingham         {
382151c032cSJim Ingham             log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str());
383151c032cSJim Ingham         }
384151c032cSJim Ingham     }
385151c032cSJim Ingham 
386151c032cSJim Ingham     if (exe_ctx.GetProcessPtr())
387151c032cSJim Ingham         exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
388151c032cSJim Ingham 
389151c032cSJim Ingham     if (args_addr_ptr != NULL)
390151c032cSJim Ingham         *args_addr_ptr = args_addr;
391151c032cSJim Ingham 
392151c032cSJim Ingham     if (return_value != lldb::eExpressionCompleted)
393151c032cSJim Ingham         return return_value;
394151c032cSJim Ingham 
395151c032cSJim Ingham     FetchFunctionResults(exe_ctx, args_addr, results);
396151c032cSJim Ingham 
397151c032cSJim Ingham     if (args_addr_ptr == NULL)
398151c032cSJim Ingham         DeallocateFunctionResults(exe_ctx, args_addr);
399151c032cSJim Ingham 
400151c032cSJim Ingham     return lldb::eExpressionCompleted;
401151c032cSJim Ingham }
402