ClangUserExpression.cpp revision 5f35a4be95aed0e5b2cb36f7d785bcbfc67284ae
1//===-- ClangUserExpression.cpp ---------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// C Includes
11#include <stdio.h>
12#if HAVE_SYS_TYPES_H
13#  include <sys/types.h>
14#endif
15
16// C++ Includes
17#include <cstdlib>
18#include <string>
19#include <map>
20
21#include "lldb/Core/ConstString.h"
22#include "lldb/Core/Log.h"
23#include "lldb/Core/StreamFile.h"
24#include "lldb/Core/StreamString.h"
25#include "lldb/Core/ValueObjectConstResult.h"
26#include "lldb/Expression/ASTResultSynthesizer.h"
27#include "lldb/Expression/ClangExpressionDeclMap.h"
28#include "lldb/Expression/ClangExpressionParser.h"
29#include "lldb/Expression/ClangFunction.h"
30#include "lldb/Expression/ClangUserExpression.h"
31#include "lldb/Expression/ExpressionSourceCode.h"
32#include "lldb/Host/Host.h"
33#include "lldb/Symbol/Block.h"
34#include "lldb/Symbol/ClangASTContext.h"
35#include "lldb/Symbol/Function.h"
36#include "lldb/Symbol/Type.h"
37#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
38#include "lldb/Symbol/VariableList.h"
39#include "lldb/Target/ExecutionContext.h"
40#include "lldb/Target/Process.h"
41#include "lldb/Target/StackFrame.h"
42#include "lldb/Target/Target.h"
43#include "lldb/Target/ThreadPlan.h"
44#include "lldb/Target/ThreadPlanCallUserExpression.h"
45
46#include "clang/AST/DeclCXX.h"
47#include "clang/AST/DeclObjC.h"
48
49using namespace lldb_private;
50
51ClangUserExpression::ClangUserExpression (const char *expr,
52                                          const char *expr_prefix,
53                                          lldb::LanguageType language,
54                                          ResultType desired_type) :
55    ClangExpression (),
56    m_expr_text (expr),
57    m_expr_prefix (expr_prefix ? expr_prefix : ""),
58    m_language (language),
59    m_transformed_text (),
60    m_desired_type (desired_type),
61    m_enforce_valid_object (false),
62    m_cplusplus (false),
63    m_objectivec (false),
64    m_static_method(false),
65    m_needs_object_ptr (false),
66    m_const_object (false),
67    m_target (NULL),
68    m_evaluated_statically (false),
69    m_const_result ()
70{
71    switch (m_language)
72    {
73    case lldb::eLanguageTypeC_plus_plus:
74        m_allow_cxx = true;
75        break;
76    case lldb::eLanguageTypeObjC:
77        m_allow_objc = true;
78        break;
79    case lldb::eLanguageTypeObjC_plus_plus:
80    default:
81        m_allow_cxx = true;
82        m_allow_objc = true;
83        break;
84    }
85}
86
87ClangUserExpression::~ClangUserExpression ()
88{
89}
90
91clang::ASTConsumer *
92ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
93{
94    ClangASTContext *clang_ast_context = m_target->GetScratchClangASTContext();
95
96    if (!clang_ast_context)
97        return NULL;
98
99    if (!m_result_synthesizer.get())
100        m_result_synthesizer.reset(new ASTResultSynthesizer(passthrough,
101                                                            *m_target));
102
103    return m_result_synthesizer.get();
104}
105
106void
107ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
108{
109    m_target = exe_ctx.GetTargetPtr();
110
111    if (!(m_allow_cxx || m_allow_objc))
112        return;
113
114    StackFrame *frame = exe_ctx.GetFramePtr();
115    if (frame == NULL)
116        return;
117
118    SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
119
120    if (!sym_ctx.function)
121        return;
122
123    // Find the block that defines the function represented by "sym_ctx"
124    Block *function_block = sym_ctx.GetFunctionBlock();
125
126    if (!function_block)
127        return;
128
129    clang::DeclContext *decl_context = function_block->GetClangDeclContext();
130
131    if (!decl_context)
132        return;
133
134    if (clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_context))
135    {
136        if (m_allow_cxx && method_decl->isInstance())
137        {
138            if (m_enforce_valid_object)
139            {
140                lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
141
142                const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context";
143
144                if (!variable_list_sp)
145                {
146                    err.SetErrorString(thisErrorString);
147                    return;
148                }
149
150                lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
151
152                if (!this_var_sp ||
153                    !this_var_sp->IsInScope(frame) ||
154                    !this_var_sp->LocationIsValidForFrame (frame))
155                {
156                    err.SetErrorString(thisErrorString);
157                    return;
158                }
159            }
160
161            m_cplusplus = true;
162            m_needs_object_ptr = true;
163        }
164    }
165    else if (clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_context))
166    {
167        if (m_allow_objc)
168        {
169            if (m_enforce_valid_object)
170            {
171                lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
172
173                const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context";
174
175                if (!variable_list_sp)
176                {
177                    err.SetErrorString(selfErrorString);
178                    return;
179                }
180
181                lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
182
183                if (!self_variable_sp ||
184                    !self_variable_sp->IsInScope(frame) ||
185                    !self_variable_sp->LocationIsValidForFrame (frame))
186                {
187                    err.SetErrorString(selfErrorString);
188                    return;
189                }
190            }
191
192            m_objectivec = true;
193            m_needs_object_ptr = true;
194
195            if (!method_decl->isInstanceMethod())
196                m_static_method = true;
197        }
198    }
199    else if (clang::FunctionDecl *function_decl = llvm::dyn_cast<clang::FunctionDecl>(decl_context))
200    {
201        // We might also have a function that said in the debug information that it captured an
202        // object pointer.  The best way to deal with getting to the ivars at present it by pretending
203        // that this is a method of a class in whatever runtime the debug info says the object pointer
204        // belongs to.  Do that here.
205
206        ClangASTMetadata *metadata = ClangASTContext::GetMetadata (&decl_context->getParentASTContext(), (uintptr_t) function_decl);
207        if (metadata && metadata->HasObjectPtr())
208        {
209            lldb::LanguageType language = metadata->GetObjectPtrLanguage();
210            if (language == lldb::eLanguageTypeC_plus_plus)
211            {
212                m_cplusplus = true;
213                m_needs_object_ptr = true;
214            }
215            else if (language == lldb::eLanguageTypeObjC)
216            {
217                m_objectivec = true;
218                m_needs_object_ptr = true;
219            }
220        }
221    }
222}
223
224// This is a really nasty hack, meant to fix Objective-C expressions of the form
225// (int)[myArray count].  Right now, because the type information for count is
226// not available, [myArray count] returns id, which can't be directly cast to
227// int without causing a clang error.
228static void
229ApplyObjcCastHack(std::string &expr)
230{
231#define OBJC_CAST_HACK_FROM "(int)["
232#define OBJC_CAST_HACK_TO   "(int)(long long)["
233
234    size_t from_offset;
235
236    while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
237        expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);
238
239#undef OBJC_CAST_HACK_TO
240#undef OBJC_CAST_HACK_FROM
241}
242
243// Another hack, meant to allow use of unichar despite it not being available in
244// the type information.  Although we could special-case it in type lookup,
245// hopefully we'll figure out a way to #include the same environment as is
246// present in the original source file rather than try to hack specific type
247// definitions in as needed.
248static void
249ApplyUnicharHack(std::string &expr)
250{
251#define UNICHAR_HACK_FROM "unichar"
252#define UNICHAR_HACK_TO   "unsigned short"
253
254    size_t from_offset;
255
256    while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos)
257        expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO);
258
259#undef UNICHAR_HACK_TO
260#undef UNICHAR_HACK_FROM
261}
262
263bool
264ClangUserExpression::Parse (Stream &error_stream,
265                            ExecutionContext &exe_ctx,
266                            lldb_private::ExecutionPolicy execution_policy,
267                            bool keep_result_in_memory)
268{
269    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
270
271    Error err;
272
273    InstallContext(exe_ctx);
274
275    ScanContext(exe_ctx, err);
276
277    if (!err.Success())
278    {
279        error_stream.Printf("warning: %s\n", err.AsCString());
280    }
281
282    StreamString m_transformed_stream;
283
284    ////////////////////////////////////
285    // Generate the expression
286    //
287
288    ApplyObjcCastHack(m_expr_text);
289    //ApplyUnicharHack(m_expr_text);
290
291    std::auto_ptr <ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(m_expr_prefix.c_str(), m_expr_text.c_str()));
292
293    lldb::LanguageType lang_type;
294
295    if (m_cplusplus)
296        lang_type = lldb::eLanguageTypeC_plus_plus;
297    else if(m_objectivec)
298        lang_type = lldb::eLanguageTypeObjC;
299    else
300        lang_type = lldb::eLanguageTypeC;
301
302    if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_static_method))
303    {
304        error_stream.PutCString ("error: couldn't construct expression body");
305        return false;
306    }
307
308    if (log)
309        log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
310
311    ////////////////////////////////////
312    // Set up the target and compiler
313    //
314
315    Target *target = exe_ctx.GetTargetPtr();
316
317    if (!target)
318    {
319        error_stream.PutCString ("error: invalid target\n");
320        return false;
321    }
322
323    //////////////////////////
324    // Parse the expression
325    //
326
327    m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
328
329    if (!m_expr_decl_map->WillParse(exe_ctx))
330    {
331        error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
332        return false;
333    }
334
335    Process *process = exe_ctx.GetProcessPtr();
336    ExecutionContextScope *exe_scope = process;
337
338    if (!exe_scope)
339        exe_scope = exe_ctx.GetTargetPtr();
340
341    ClangExpressionParser parser(exe_scope, *this);
342
343    unsigned num_errors = parser.Parse (error_stream);
344
345    if (num_errors)
346    {
347        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
348
349        m_expr_decl_map->DidParse();
350
351        return false;
352    }
353
354    //////////////////////////////////////////////////////////////////////////////////////////
355    // Prepare the output of the parser for execution, evaluating it statically if possible
356    //
357
358    if (execution_policy != eExecutionPolicyNever && process)
359        m_data_allocator.reset(new ProcessDataAllocator(*process));
360
361    Error jit_error = parser.PrepareForExecution (m_jit_alloc,
362                                                  m_jit_start_addr,
363                                                  m_jit_end_addr,
364                                                  exe_ctx,
365                                                  m_data_allocator.get(),
366                                                  m_evaluated_statically,
367                                                  m_const_result,
368                                                  execution_policy);
369
370    if (log && m_data_allocator.get())
371    {
372        StreamString dump_string;
373        m_data_allocator->Dump(dump_string);
374
375        log->Printf("Data buffer contents:\n%s", dump_string.GetString().c_str());
376    }
377
378    if (jit_error.Success())
379    {
380        if (process && m_jit_alloc != LLDB_INVALID_ADDRESS)
381            m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
382        return true;
383    }
384    else
385    {
386        const char *error_cstr = jit_error.AsCString();
387        if (error_cstr && error_cstr[0])
388            error_stream.Printf ("error: %s\n", error_cstr);
389        else
390            error_stream.Printf ("error: expression can't be interpreted or run\n");
391        return false;
392    }
393}
394
395bool
396ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
397                                                    ExecutionContext &exe_ctx,
398                                                    lldb::addr_t &struct_address,
399                                                    lldb::addr_t &object_ptr,
400                                                    lldb::addr_t &cmd_ptr)
401{
402    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
403
404    lldb::TargetSP target;
405    lldb::ProcessSP process;
406    lldb::StackFrameSP frame;
407
408    if (!LockAndCheckContext(exe_ctx,
409                             target,
410                             process,
411                             frame))
412    {
413        error_stream.Printf("The context has changed before we could JIT the expression!");
414        return false;
415    }
416
417    if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
418    {
419        Error materialize_error;
420
421        if (m_needs_object_ptr)
422        {
423            ConstString object_name;
424
425            if (m_cplusplus)
426            {
427                object_name.SetCString("this");
428            }
429            else if (m_objectivec)
430            {
431                object_name.SetCString("self");
432            }
433            else
434            {
435                error_stream.Printf("Need object pointer but don't know the language\n");
436                return false;
437            }
438
439            if (!(m_expr_decl_map->GetObjectPointer(object_ptr, object_name, materialize_error)))
440            {
441                error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", materialize_error.AsCString());
442                object_ptr = 0;
443            }
444
445            if (m_objectivec)
446            {
447                ConstString cmd_name("_cmd");
448
449                if (!(m_expr_decl_map->GetObjectPointer(cmd_ptr, cmd_name, materialize_error, true)))
450                {
451                    error_stream.Printf("warning: couldn't get object pointer (substituting NULL): %s\n", materialize_error.AsCString());
452                    cmd_ptr = 0;
453                }
454            }
455        }
456
457        if (!m_expr_decl_map->Materialize(struct_address, materialize_error))
458        {
459            error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
460            return false;
461        }
462
463#if 0
464		// jingham: look here
465        StreamFile logfile ("/tmp/exprs.txt", "a");
466        logfile.Printf("0x%16.16" PRIx64 ": thread = 0x%4.4x, expr = '%s'\n", m_jit_start_addr, exe_ctx.thread ? exe_ctx.thread->GetID() : -1, m_expr_text.c_str());
467#endif
468
469        if (log)
470        {
471            log->Printf("-- [ClangUserExpression::PrepareToExecuteJITExpression] Materializing for execution --");
472
473            log->Printf("  Function address  : 0x%" PRIx64, (uint64_t)m_jit_start_addr);
474
475            if (m_needs_object_ptr)
476                log->Printf("  Object pointer    : 0x%" PRIx64, (uint64_t)object_ptr);
477
478            log->Printf("  Structure address : 0x%" PRIx64, (uint64_t)struct_address);
479
480            StreamString args;
481
482            Error dump_error;
483
484            if (struct_address)
485            {
486                if (!m_expr_decl_map->DumpMaterializedStruct(args, dump_error))
487                {
488                    log->Printf("  Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
489                }
490                else
491                {
492                    log->Printf("  Structure contents:\n%s", args.GetData());
493                }
494            }
495        }
496    }
497    return true;
498}
499
500ThreadPlan *
501ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
502                                                          ExecutionContext &exe_ctx)
503{
504    lldb::addr_t struct_address;
505
506    lldb::addr_t object_ptr = 0;
507    lldb::addr_t cmd_ptr = 0;
508
509    PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr);
510
511    // FIXME: This should really return a ThreadPlanCallUserExpression, in order to make sure that we don't release the
512    // ClangUserExpression resources before the thread plan finishes execution in the target.  But because we are
513    // forcing unwind_on_error to be true here, in practical terms that can't happen.
514
515    return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
516                                                       m_jit_start_addr,
517                                                       struct_address,
518                                                       error_stream,
519                                                       true,
520                                                       true,
521                                                       (m_needs_object_ptr ? &object_ptr : NULL),
522                                                       (m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL);
523}
524
525bool
526ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
527                                           ExecutionContext &exe_ctx,
528                                           lldb::ClangExpressionVariableSP &result,
529                                           lldb::addr_t function_stack_pointer)
530{
531    Error expr_error;
532
533    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
534
535    if (log)
536    {
537        log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --");
538
539        StreamString args;
540
541        Error dump_error;
542
543        if (!m_expr_decl_map->DumpMaterializedStruct(args, dump_error))
544        {
545            log->Printf("  Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
546        }
547        else
548        {
549            log->Printf("  Structure contents:\n%s", args.GetData());
550        }
551    }
552
553    lldb::addr_t function_stack_bottom = function_stack_pointer - Host::GetPageSize();
554
555
556    if (!m_expr_decl_map->Dematerialize(result, function_stack_pointer, function_stack_bottom, expr_error))
557    {
558        error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
559        return false;
560    }
561
562    if (result)
563        result->TransferAddress();
564
565    return true;
566}
567
568ExecutionResults
569ClangUserExpression::Execute (Stream &error_stream,
570                              ExecutionContext &exe_ctx,
571                              bool discard_on_error,
572                              ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
573                              lldb::ClangExpressionVariableSP &result,
574                              bool run_others,
575                              uint32_t timeout_usec)
576{
577    // The expression log is quite verbose, and if you're just tracking the execution of the
578    // expression, it's quite convenient to have these logs come out with the STEP log as well.
579    lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
580
581    if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
582    {
583        lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
584
585        lldb::addr_t object_ptr = 0;
586        lldb::addr_t cmd_ptr = 0;
587
588        if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr))
589        {
590            error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__);
591            return eExecutionSetupError;
592        }
593
594        const bool stop_others = true;
595        const bool try_all_threads = true;
596
597        Address wrapper_address (m_jit_start_addr);
598        lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
599                                                                          wrapper_address,
600                                                                          struct_address,
601                                                                          stop_others,
602                                                                          discard_on_error,
603                                                                          (m_needs_object_ptr ? &object_ptr : NULL),
604                                                                          ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
605                                                                          shared_ptr_to_me));
606
607        if (!call_plan_sp || !call_plan_sp->ValidatePlan (NULL))
608            return eExecutionSetupError;
609
610        lldb::addr_t function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer();
611
612        call_plan_sp->SetPrivate(true);
613
614        if (log)
615            log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
616
617        if (exe_ctx.GetProcessPtr())
618            exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
619
620        ExecutionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
621                                                                                   call_plan_sp,
622                                                                                   stop_others,
623                                                                                   try_all_threads,
624                                                                                   discard_on_error,
625                                                                                   timeout_usec,
626                                                                                   error_stream);
627
628        if (exe_ctx.GetProcessPtr())
629            exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
630
631        if (log)
632            log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
633
634        if (execution_result == eExecutionInterrupted)
635        {
636            const char *error_desc = NULL;
637
638            if (call_plan_sp)
639            {
640                lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
641                if (real_stop_info_sp)
642                    error_desc = real_stop_info_sp->GetDescription();
643            }
644            if (error_desc)
645                error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
646            else
647                error_stream.Printf ("Execution was interrupted.");
648
649            if (discard_on_error)
650                error_stream.Printf ("\nThe process has been returned to the state before execution.");
651            else
652                error_stream.Printf ("\nThe process has been left at the point where it was interrupted.");
653
654            return execution_result;
655        }
656        else if (execution_result != eExecutionCompleted)
657        {
658            error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
659            return execution_result;
660        }
661
662        if  (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_pointer))
663            return eExecutionCompleted;
664        else
665        {
666            error_stream.Printf("Errored out in %s: Couldn't FinalizeJITExpression", __FUNCTION__);
667            return eExecutionSetupError;
668        }
669    }
670    else
671    {
672        error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
673        return eExecutionSetupError;
674    }
675}
676
677ExecutionResults
678ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
679                               lldb_private::ExecutionPolicy execution_policy,
680                               lldb::LanguageType language,
681                               ResultType desired_type,
682                               bool discard_on_error,
683                               const char *expr_cstr,
684                               const char *expr_prefix,
685                               lldb::ValueObjectSP &result_valobj_sp,
686                               bool run_others,
687                               uint32_t timeout_usec)
688{
689    Error error;
690    return EvaluateWithError (exe_ctx,
691                              execution_policy,
692                              language,
693                              desired_type,
694                              discard_on_error,
695                              expr_cstr,
696                              expr_prefix,
697                              result_valobj_sp,
698                              error,
699                              run_others,
700                              timeout_usec);
701}
702
703ExecutionResults
704ClangUserExpression::EvaluateWithError (ExecutionContext &exe_ctx,
705                                        lldb_private::ExecutionPolicy execution_policy,
706                                        lldb::LanguageType language,
707                                        ResultType desired_type,
708                                        bool discard_on_error,
709                                        const char *expr_cstr,
710                                        const char *expr_prefix,
711                                        lldb::ValueObjectSP &result_valobj_sp,
712                                        Error &error,
713                                        bool run_others,
714                                        uint32_t timeout_usec)
715{
716    lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
717
718    ExecutionResults execution_results = eExecutionSetupError;
719
720    Process *process = exe_ctx.GetProcessPtr();
721
722    if (process == NULL || process->GetState() != lldb::eStateStopped)
723    {
724        if (execution_policy == eExecutionPolicyAlways)
725        {
726            if (log)
727                log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
728
729            error.SetErrorString ("expression needed to run but couldn't");
730
731            return execution_results;
732        }
733    }
734
735    if (process == NULL || !process->CanJIT())
736        execution_policy = eExecutionPolicyNever;
737
738    ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix, language, desired_type));
739
740    StreamString error_stream;
741
742    if (log)
743        log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
744
745    const bool keep_expression_in_memory = true;
746
747    if (!user_expression_sp->Parse (error_stream, exe_ctx, execution_policy, keep_expression_in_memory))
748    {
749        if (error_stream.GetString().empty())
750            error.SetErrorString ("expression failed to parse, unknown error");
751        else
752            error.SetErrorString (error_stream.GetString().c_str());
753    }
754    else
755    {
756        lldb::ClangExpressionVariableSP expr_result;
757
758        if (user_expression_sp->EvaluatedStatically())
759        {
760            if (log)
761                log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant ==");
762
763            if (user_expression_sp->m_const_result)
764                result_valobj_sp = user_expression_sp->m_const_result->GetValueObject();
765            else
766                error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
767
768            execution_results = eExecutionCompleted;
769        }
770        else if (execution_policy == eExecutionPolicyNever)
771        {
772            if (log)
773                log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
774
775            if (error_stream.GetString().empty())
776                error.SetErrorString ("expression needed to run but couldn't");
777        }
778        else
779        {
780            error_stream.GetString().clear();
781
782            if (log)
783                log->Printf("== [ClangUserExpression::Evaluate] Executing expression ==");
784
785            execution_results = user_expression_sp->Execute (error_stream,
786                                                             exe_ctx,
787                                                             discard_on_error,
788                                                             user_expression_sp,
789                                                             expr_result,
790                                                             run_others,
791                                                             timeout_usec);
792
793            if (execution_results != eExecutionCompleted)
794            {
795                if (log)
796                    log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally ==");
797
798                if (error_stream.GetString().empty())
799                    error.SetErrorString ("expression failed to execute, unknown error");
800                else
801                    error.SetErrorString (error_stream.GetString().c_str());
802            }
803            else
804            {
805                if (expr_result)
806                {
807                    result_valobj_sp = expr_result->GetValueObject();
808
809                    if (log)
810                        log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString());
811                }
812                else
813                {
814                    if (log)
815                        log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result ==");
816
817                    error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
818                }
819            }
820        }
821    }
822
823    if (result_valobj_sp.get() == NULL)
824        result_valobj_sp = ValueObjectConstResult::Create (NULL, error);
825
826    return execution_results;
827}
828