2011-05-23 21:40:23 +00:00
//===-- ClangUserExpression.cpp ---------------------------------*- C++ -*-===//
2010-08-27 01:01:44 +00:00
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// C Includes
# include <stdio.h>
# if HAVE_SYS_TYPES_H
# include <sys / types.h>
# endif
// C++ Includes
# include <cstdlib>
# include <string>
# include <map>
# include "lldb/Core/ConstString.h"
# include "lldb/Core/Log.h"
2011-01-18 19:36:39 +00:00
# include "lldb/Core/StreamFile.h"
2010-08-27 01:01:44 +00:00
# include "lldb/Core/StreamString.h"
2010-10-05 03:13:51 +00:00
# include "lldb/Core/ValueObjectConstResult.h"
2010-12-16 03:17:46 +00:00
# include "lldb/Expression/ASTResultSynthesizer.h"
2010-08-27 01:01:44 +00:00
# include "lldb/Expression/ClangExpressionDeclMap.h"
# include "lldb/Expression/ClangExpressionParser.h"
# include "lldb/Expression/ClangFunction.h"
# include "lldb/Expression/ClangUserExpression.h"
2011-09-26 18:45:31 +00:00
# include "lldb/Expression/ExpressionSourceCode.h"
2013-04-16 23:25:35 +00:00
# include "lldb/Expression/IRExecutionUnit.h"
2013-04-18 22:06:33 +00:00
# include "lldb/Expression/IRInterpreter.h"
2013-04-11 00:09:05 +00:00
# include "lldb/Expression/Materializer.h"
2010-08-27 01:01:44 +00:00
# include "lldb/Host/Host.h"
2012-08-29 21:13:06 +00:00
# include "lldb/Symbol/Block.h"
2012-10-30 23:35:54 +00:00
# include "lldb/Symbol/ClangASTContext.h"
# include "lldb/Symbol/Function.h"
# include "lldb/Symbol/Type.h"
# include "lldb/Symbol/ClangExternalASTSourceCommon.h"
2010-09-21 00:44:12 +00:00
# include "lldb/Symbol/VariableList.h"
2010-08-27 01:01:44 +00:00
# include "lldb/Target/ExecutionContext.h"
2010-11-04 01:54:29 +00:00
# include "lldb/Target/Process.h"
2013-11-04 09:33:30 +00:00
# include "lldb/Target/StackFrame.h"
2010-08-27 01:01:44 +00:00
# include "lldb/Target/Target.h"
2010-11-30 02:22:11 +00:00
# include "lldb/Target/ThreadPlan.h"
# include "lldb/Target/ThreadPlanCallUserExpression.h"
2010-08-27 01:01:44 +00:00
2011-08-05 23:43:37 +00:00
# include "clang/AST/DeclCXX.h"
# include "clang/AST/DeclObjC.h"
2010-08-27 01:01:44 +00:00
using namespace lldb_private ;
2010-10-29 00:29:03 +00:00
ClangUserExpression : : ClangUserExpression ( const char * expr ,
2011-11-07 23:35:40 +00:00
const char * expr_prefix ,
2011-12-21 22:22:58 +00:00
lldb : : LanguageType language ,
ResultType desired_type ) :
2011-01-19 23:00:49 +00:00
ClangExpression ( ) ,
2013-04-27 02:19:33 +00:00
m_stack_frame_bottom ( LLDB_INVALID_ADDRESS ) ,
m_stack_frame_top ( LLDB_INVALID_ADDRESS ) ,
2011-01-19 23:00:49 +00:00
m_expr_text ( expr ) ,
m_expr_prefix ( expr_prefix ? expr_prefix : " " ) ,
2011-11-07 23:35:40 +00:00
m_language ( language ) ,
2011-01-19 23:00:49 +00:00
m_transformed_text ( ) ,
2011-12-21 22:22:58 +00:00
m_desired_type ( desired_type ) ,
2012-12-06 01:35:38 +00:00
m_enforce_valid_object ( true ) ,
2011-01-19 23:00:49 +00:00
m_cplusplus ( false ) ,
m_objectivec ( false ) ,
2012-04-03 08:46:13 +00:00
m_static_method ( false ) ,
2011-01-19 23:00:49 +00:00
m_needs_object_ptr ( false ) ,
2011-05-07 01:06:41 +00:00
m_const_object ( false ) ,
2011-10-31 22:50:49 +00:00
m_target ( NULL ) ,
2013-04-27 02:19:33 +00:00
m_can_interpret ( false ) ,
m_materialized_address ( LLDB_INVALID_ADDRESS )
2010-08-27 01:01:44 +00:00
{
2011-11-07 23:35:40 +00:00
switch ( m_language )
{
case lldb : : eLanguageTypeC_plus_plus :
m_allow_cxx = true ;
break ;
case lldb : : eLanguageTypeObjC :
m_allow_objc = true ;
break ;
case lldb : : eLanguageTypeObjC_plus_plus :
default :
m_allow_cxx = true ;
m_allow_objc = true ;
break ;
}
2010-08-27 01:01:44 +00:00
}
2010-08-27 23:31:21 +00:00
ClangUserExpression : : ~ ClangUserExpression ( )
{
}
2010-08-27 01:01:44 +00:00
clang : : ASTConsumer *
ClangUserExpression : : ASTTransformer ( clang : : ASTConsumer * passthrough )
2013-10-10 00:39:23 +00:00
{
m_result_synthesizer . reset ( new ASTResultSynthesizer ( passthrough ,
* m_target ) ) ;
2011-10-08 00:21:35 +00:00
return m_result_synthesizer . get ( ) ;
2010-08-27 01:01:44 +00:00
}
2010-09-21 00:44:12 +00:00
void
2011-11-04 02:09:33 +00:00
ClangUserExpression : : ScanContext ( ExecutionContext & exe_ctx , Error & err )
2010-09-21 00:44:12 +00:00
{
2013-03-27 23:08:40 +00:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2012-12-01 00:08:33 +00:00
if ( log )
log - > Printf ( " ClangUserExpression::ScanContext() " ) ;
2011-09-22 04:58:26 +00:00
m_target = exe_ctx . GetTargetPtr ( ) ;
2011-09-12 23:21:58 +00:00
2011-11-07 23:35:40 +00:00
if ( ! ( m_allow_cxx | | m_allow_objc ) )
2012-12-01 00:08:33 +00:00
{
if ( log )
log - > Printf ( " [CUE::SC] Settings inhibit C++ and Objective-C " ) ;
2011-11-07 23:35:40 +00:00
return ;
2012-12-01 00:08:33 +00:00
}
2011-11-07 23:35:40 +00:00
2013-11-04 09:33:30 +00:00
StackFrame * frame = exe_ctx . GetFramePtr ( ) ;
2011-09-22 04:58:26 +00:00
if ( frame = = NULL )
2012-12-01 00:08:33 +00:00
{
if ( log )
log - > Printf ( " [CUE::SC] Null stack frame " ) ;
2010-09-21 00:44:12 +00:00
return ;
2012-12-01 00:08:33 +00:00
}
2010-09-21 00:44:12 +00:00
2012-07-13 21:20:29 +00:00
SymbolContext sym_ctx = frame - > GetSymbolContext ( lldb : : eSymbolContextFunction | lldb : : eSymbolContextBlock ) ;
2010-12-01 21:35:54 +00:00
2011-08-05 23:43:37 +00:00
if ( ! sym_ctx . function )
2012-12-01 00:08:33 +00:00
{
if ( log )
log - > Printf ( " [CUE::SC] Null function " ) ;
2011-08-05 23:43:37 +00:00
return ;
2012-12-01 00:08:33 +00:00
}
2011-08-05 23:43:37 +00:00
2012-07-14 00:53:55 +00:00
// Find the block that defines the function represented by "sym_ctx"
Block * function_block = sym_ctx . GetFunctionBlock ( ) ;
2011-08-05 23:43:37 +00:00
2012-07-14 00:53:55 +00:00
if ( ! function_block )
2012-12-01 00:08:33 +00:00
{
if ( log )
log - > Printf ( " [CUE::SC] Null function block " ) ;
2012-07-14 00:53:55 +00:00
return ;
2012-12-01 00:08:33 +00:00
}
2012-07-14 00:53:55 +00:00
clang : : DeclContext * decl_context = function_block - > GetClangDeclContext ( ) ;
2011-08-05 23:43:37 +00:00
if ( ! decl_context )
2012-12-01 00:08:33 +00:00
{
if ( log )
log - > Printf ( " [CUE::SC] Null decl context " ) ;
2011-08-05 23:43:37 +00:00
return ;
2012-12-01 00:08:33 +00:00
}
2011-08-05 23:43:37 +00:00
if ( clang : : CXXMethodDecl * method_decl = llvm : : dyn_cast < clang : : CXXMethodDecl > ( decl_context ) )
2010-12-01 21:35:54 +00:00
{
2011-11-07 23:35:40 +00:00
if ( m_allow_cxx & & method_decl - > isInstance ( ) )
2010-12-01 21:35:54 +00:00
{
2011-12-13 01:42:04 +00:00
if ( m_enforce_valid_object )
2011-11-04 02:09:33 +00:00
{
2012-07-14 00:53:55 +00:00
lldb : : VariableListSP variable_list_sp ( function_block - > GetBlockVariableList ( true ) ) ;
2011-12-13 01:42:04 +00:00
const char * thisErrorString = " Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context " ;
2012-07-14 00:53:55 +00:00
if ( ! variable_list_sp )
2011-12-13 01:42:04 +00:00
{
err . SetErrorString ( thisErrorString ) ;
return ;
}
2012-07-14 00:53:55 +00:00
lldb : : VariableSP this_var_sp ( variable_list_sp - > FindVariable ( ConstString ( " this " ) ) ) ;
2011-12-13 01:42:04 +00:00
2012-07-14 00:53:55 +00:00
if ( ! this_var_sp | |
! this_var_sp - > IsInScope ( frame ) | |
! this_var_sp - > LocationIsValidForFrame ( frame ) )
2011-12-13 01:42:04 +00:00
{
err . SetErrorString ( thisErrorString ) ;
return ;
}
2011-11-04 02:09:33 +00:00
}
2011-08-05 23:43:37 +00:00
m_cplusplus = true ;
2011-09-26 18:45:31 +00:00
m_needs_object_ptr = true ;
2010-12-01 21:35:54 +00:00
}
}
2011-08-05 23:43:37 +00:00
else if ( clang : : ObjCMethodDecl * method_decl = llvm : : dyn_cast < clang : : ObjCMethodDecl > ( decl_context ) )
2011-11-04 02:09:33 +00:00
{
2011-11-15 02:11:17 +00:00
if ( m_allow_objc )
2011-09-26 18:45:31 +00:00
{
2011-12-13 01:42:04 +00:00
if ( m_enforce_valid_object )
2011-11-04 02:09:33 +00:00
{
2012-07-14 00:53:55 +00:00
lldb : : VariableListSP variable_list_sp ( function_block - > GetBlockVariableList ( true ) ) ;
2011-12-13 01:42:04 +00:00
const char * selfErrorString = " Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context " ;
2012-07-14 00:53:55 +00:00
if ( ! variable_list_sp )
2011-12-13 01:42:04 +00:00
{
err . SetErrorString ( selfErrorString ) ;
return ;
}
2012-07-14 00:53:55 +00:00
lldb : : VariableSP self_variable_sp = variable_list_sp - > FindVariable ( ConstString ( " self " ) ) ;
2011-12-13 01:42:04 +00:00
2012-07-14 00:53:55 +00:00
if ( ! self_variable_sp | |
! self_variable_sp - > IsInScope ( frame ) | |
! self_variable_sp - > LocationIsValidForFrame ( frame ) )
2011-12-13 01:42:04 +00:00
{
err . SetErrorString ( selfErrorString ) ;
return ;
}
2011-11-04 02:09:33 +00:00
}
2011-08-05 23:43:37 +00:00
m_objectivec = true ;
2011-09-26 18:45:31 +00:00
m_needs_object_ptr = true ;
2011-11-15 02:11:17 +00:00
if ( ! method_decl - > isInstanceMethod ( ) )
m_static_method = true ;
2011-09-26 18:45:31 +00:00
}
2010-12-01 21:35:54 +00:00
}
2012-10-30 23:35:54 +00:00
else if ( clang : : FunctionDecl * function_decl = llvm : : dyn_cast < clang : : FunctionDecl > ( decl_context ) )
{
// We might also have a function that said in the debug information that it captured an
// object pointer. The best way to deal with getting to the ivars at present it by pretending
// that this is a method of a class in whatever runtime the debug info says the object pointer
// belongs to. Do that here.
2013-03-27 01:48:02 +00:00
ClangASTMetadata * metadata = ClangASTContext : : GetMetadata ( & decl_context - > getParentASTContext ( ) , function_decl ) ;
2012-10-30 23:35:54 +00:00
if ( metadata & & metadata - > HasObjectPtr ( ) )
{
lldb : : LanguageType language = metadata - > GetObjectPtrLanguage ( ) ;
if ( language = = lldb : : eLanguageTypeC_plus_plus )
{
2013-01-19 01:49:02 +00:00
if ( m_enforce_valid_object )
{
lldb : : VariableListSP variable_list_sp ( function_block - > GetBlockVariableList ( true ) ) ;
const char * thisErrorString = " Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context " ;
if ( ! variable_list_sp )
{
err . SetErrorString ( thisErrorString ) ;
return ;
}
lldb : : VariableSP this_var_sp ( variable_list_sp - > FindVariable ( ConstString ( " this " ) ) ) ;
if ( ! this_var_sp | |
! this_var_sp - > IsInScope ( frame ) | |
! this_var_sp - > LocationIsValidForFrame ( frame ) )
{
err . SetErrorString ( thisErrorString ) ;
return ;
}
}
2012-10-30 23:35:54 +00:00
m_cplusplus = true ;
m_needs_object_ptr = true ;
}
else if ( language = = lldb : : eLanguageTypeObjC )
{
2013-01-19 01:49:02 +00:00
if ( m_enforce_valid_object )
{
lldb : : VariableListSP variable_list_sp ( function_block - > GetBlockVariableList ( true ) ) ;
const char * selfErrorString = " Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context " ;
if ( ! variable_list_sp )
{
err . SetErrorString ( selfErrorString ) ;
return ;
}
lldb : : VariableSP self_variable_sp = variable_list_sp - > FindVariable ( ConstString ( " self " ) ) ;
if ( ! self_variable_sp | |
! self_variable_sp - > IsInScope ( frame ) | |
! self_variable_sp - > LocationIsValidForFrame ( frame ) )
{
err . SetErrorString ( selfErrorString ) ;
return ;
}
Type * self_type = self_variable_sp - > GetType ( ) ;
if ( ! self_type )
{
err . SetErrorString ( selfErrorString ) ;
return ;
}
2013-07-11 22:46:58 +00:00
ClangASTType self_clang_type = self_type - > GetClangForwardType ( ) ;
2013-01-19 01:49:02 +00:00
2013-07-11 22:46:58 +00:00
if ( ! self_clang_type )
2013-01-19 01:49:02 +00:00
{
err . SetErrorString ( selfErrorString ) ;
return ;
}
2013-07-11 22:46:58 +00:00
if ( self_clang_type . IsObjCClassType ( ) )
2013-01-19 01:49:02 +00:00
{
return ;
}
2013-07-11 22:46:58 +00:00
else if ( self_clang_type . IsObjCObjectPointerType ( ) )
2013-01-19 01:49:02 +00:00
{
m_objectivec = true ;
m_needs_object_ptr = true ;
}
else
{
err . SetErrorString ( selfErrorString ) ;
return ;
}
}
else
{
m_objectivec = true ;
m_needs_object_ptr = true ;
}
2012-10-30 23:35:54 +00:00
}
}
}
2010-09-21 00:44:12 +00:00
}
2013-04-19 07:09:15 +00:00
void
ClangUserExpression : : InstallContext ( ExecutionContext & exe_ctx )
{
m_process_wp = exe_ctx . GetProcessSP ( ) ;
2013-11-04 09:33:30 +00:00
lldb : : StackFrameSP frame_sp = exe_ctx . GetFrameSP ( ) ;
2013-04-19 07:09:15 +00:00
if ( frame_sp )
m_address = frame_sp - > GetFrameCodeAddress ( ) ;
}
bool
ClangUserExpression : : LockAndCheckContext ( ExecutionContext & exe_ctx ,
lldb : : TargetSP & target_sp ,
lldb : : ProcessSP & process_sp ,
2013-11-04 09:33:30 +00:00
lldb : : StackFrameSP & frame_sp )
2013-04-19 07:09:15 +00:00
{
lldb : : ProcessSP expected_process_sp = m_process_wp . lock ( ) ;
process_sp = exe_ctx . GetProcessSP ( ) ;
if ( process_sp ! = expected_process_sp )
return false ;
process_sp = exe_ctx . GetProcessSP ( ) ;
target_sp = exe_ctx . GetTargetSP ( ) ;
frame_sp = exe_ctx . GetFrameSP ( ) ;
if ( m_address . IsValid ( ) )
{
if ( ! frame_sp )
return false ;
else
return ( 0 = = Address : : CompareLoadAddress ( m_address , frame_sp - > GetFrameCodeAddress ( ) , target_sp . get ( ) ) ) ;
}
return true ;
}
bool
ClangUserExpression : : MatchesContext ( ExecutionContext & exe_ctx )
{
lldb : : TargetSP target_sp ;
lldb : : ProcessSP process_sp ;
2013-11-04 09:33:30 +00:00
lldb : : StackFrameSP frame_sp ;
2013-04-19 07:09:15 +00:00
return LockAndCheckContext ( exe_ctx , target_sp , process_sp , frame_sp ) ;
}
2010-10-22 23:25:16 +00:00
// This is a really nasty hack, meant to fix Objective-C expressions of the form
// (int)[myArray count]. Right now, because the type information for count is
// not available, [myArray count] returns id, which can't be directly cast to
// int without causing a clang error.
static void
ApplyObjcCastHack ( std : : string & expr )
{
# define OBJC_CAST_HACK_FROM "(int)["
# define OBJC_CAST_HACK_TO "(int)(long long)["
size_t from_offset ;
while ( ( from_offset = expr . find ( OBJC_CAST_HACK_FROM ) ) ! = expr . npos )
expr . replace ( from_offset , sizeof ( OBJC_CAST_HACK_FROM ) - 1 , OBJC_CAST_HACK_TO ) ;
# undef OBJC_CAST_HACK_TO
# undef OBJC_CAST_HACK_FROM
}
2010-10-24 20:45:49 +00:00
// Another hack, meant to allow use of unichar despite it not being available in
// the type information. Although we could special-case it in type lookup,
// hopefully we'll figure out a way to #include the same environment as is
// present in the original source file rather than try to hack specific type
// definitions in as needed.
static void
ApplyUnicharHack ( std : : string & expr )
{
# define UNICHAR_HACK_FROM "unichar"
# define UNICHAR_HACK_TO "unsigned short"
size_t from_offset ;
while ( ( from_offset = expr . find ( UNICHAR_HACK_FROM ) ) ! = expr . npos )
expr . replace ( from_offset , sizeof ( UNICHAR_HACK_FROM ) - 1 , UNICHAR_HACK_TO ) ;
# undef UNICHAR_HACK_TO
# undef UNICHAR_HACK_FROM
}
2010-10-22 23:25:16 +00:00
bool
2010-11-19 02:52:21 +00:00
ClangUserExpression : : Parse ( Stream & error_stream ,
ExecutionContext & exe_ctx ,
2011-09-15 02:13:07 +00:00
lldb_private : : ExecutionPolicy execution_policy ,
2011-05-07 01:06:41 +00:00
bool keep_result_in_memory )
2010-08-27 01:01:44 +00:00
{
2013-03-27 23:08:40 +00:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-08-27 01:01:44 +00:00
2011-11-04 02:09:33 +00:00
Error err ;
2012-02-10 01:22:05 +00:00
InstallContext ( exe_ctx ) ;
2011-11-04 02:09:33 +00:00
ScanContext ( exe_ctx , err ) ;
if ( ! err . Success ( ) )
{
error_stream . Printf ( " warning: %s \n " , err . AsCString ( ) ) ;
}
2010-09-21 00:44:12 +00:00
StreamString m_transformed_stream ;
////////////////////////////////////
// Generate the expression
//
2010-10-22 23:25:16 +00:00
ApplyObjcCastHack ( m_expr_text ) ;
2010-10-27 03:32:59 +00:00
//ApplyUnicharHack(m_expr_text);
2010-09-21 00:44:12 +00:00
2013-04-18 22:45:39 +00:00
std : : unique_ptr < ExpressionSourceCode > source_code ( ExpressionSourceCode : : CreateWrapped ( m_expr_prefix . c_str ( ) , m_expr_text . c_str ( ) ) ) ;
2011-09-26 18:45:31 +00:00
lldb : : LanguageType lang_type ;
2010-09-21 00:44:12 +00:00
if ( m_cplusplus )
2011-09-26 18:45:31 +00:00
lang_type = lldb : : eLanguageTypeC_plus_plus ;
else if ( m_objectivec )
lang_type = lldb : : eLanguageTypeObjC ;
2010-09-21 00:44:12 +00:00
else
2011-09-26 18:45:31 +00:00
lang_type = lldb : : eLanguageTypeC ;
2011-11-15 02:11:17 +00:00
if ( ! source_code - > GetText ( m_transformed_text , lang_type , m_const_object , m_static_method ) )
2010-09-21 00:44:12 +00:00
{
2011-09-26 18:45:31 +00:00
error_stream . PutCString ( " error: couldn't construct expression body " ) ;
return false ;
2010-09-21 00:44:12 +00:00
}
if ( log )
log - > Printf ( " Parsing the following code: \n %s " , m_transformed_text . c_str ( ) ) ;
2010-08-27 01:01:44 +00:00
////////////////////////////////////
// Set up the target and compiler
//
2011-09-22 04:58:26 +00:00
Target * target = exe_ctx . GetTargetPtr ( ) ;
2010-08-27 01:01:44 +00:00
if ( ! target )
{
error_stream . PutCString ( " error: invalid target \n " ) ;
return false ;
}
//////////////////////////
// Parse the expression
//
2011-12-21 22:22:58 +00:00
2013-04-11 00:09:05 +00:00
m_materializer_ap . reset ( new Materializer ( ) ) ;
2011-10-29 01:58:46 +00:00
m_expr_decl_map . reset ( new ClangExpressionDeclMap ( keep_result_in_memory , exe_ctx ) ) ;
2010-12-03 01:38:59 +00:00
2013-07-11 22:46:58 +00:00
class OnExit
{
public :
typedef std : : function < void ( void ) > Callback ;
OnExit ( Callback const & callback ) :
m_callback ( callback )
{
}
~ OnExit ( )
{
m_callback ( ) ;
}
private :
Callback m_callback ;
} ;
OnExit on_exit ( [ this ] ( ) { m_expr_decl_map . reset ( ) ; } ) ;
2013-04-11 00:09:05 +00:00
if ( ! m_expr_decl_map - > WillParse ( exe_ctx , m_materializer_ap . get ( ) ) )
2011-08-01 18:18:33 +00:00
{
error_stream . PutCString ( " error: current process state is unsuitable for expression parsing \n " ) ;
2013-08-23 00:36:14 +00:00
m_expr_decl_map . reset ( ) ; // We are being careful here in the case of breakpoint conditions.
2011-08-01 18:18:33 +00:00
return false ;
}
2010-08-27 01:01:44 +00:00
2011-09-22 04:58:26 +00:00
Process * process = exe_ctx . GetProcessPtr ( ) ;
2012-02-08 18:43:35 +00:00
ExecutionContextScope * exe_scope = process ;
if ( ! exe_scope )
exe_scope = exe_ctx . GetTargetPtr ( ) ;
ClangExpressionParser parser ( exe_scope , * this ) ;
2010-08-27 01:01:44 +00:00
unsigned num_errors = parser . Parse ( error_stream ) ;
if ( num_errors )
{
error_stream . Printf ( " error: %d errors parsing expression \n " , num_errors ) ;
2010-12-03 01:38:59 +00:00
2013-08-23 00:36:14 +00:00
m_expr_decl_map . reset ( ) ; // We are being careful here in the case of breakpoint conditions.
2010-12-03 01:38:59 +00:00
2010-08-27 01:01:44 +00:00
return false ;
}
2011-09-15 02:13:07 +00:00
//////////////////////////////////////////////////////////////////////////////////////////
// Prepare the output of the parser for execution, evaluating it statically if possible
2010-08-27 01:01:44 +00:00
//
2013-03-19 00:10:07 +00:00
Error jit_error = parser . PrepareForExecution ( m_jit_start_addr ,
2011-09-15 02:13:07 +00:00
m_jit_end_addr ,
2013-04-05 02:22:57 +00:00
m_execution_unit_ap ,
2011-09-15 02:13:07 +00:00
exe_ctx ,
2013-04-18 22:06:33 +00:00
m_can_interpret ,
2011-09-15 02:13:07 +00:00
execution_policy ) ;
2013-08-23 00:36:14 +00:00
m_expr_decl_map . reset ( ) ; // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions.
2011-10-12 22:20:02 +00:00
2010-08-27 01:01:44 +00:00
if ( jit_error . Success ( ) )
{
2013-03-19 00:10:07 +00:00
if ( process & & m_jit_start_addr ! = LLDB_INVALID_ADDRESS )
2012-09-18 00:08:47 +00:00
m_jit_process_wp = lldb : : ProcessWP ( process - > shared_from_this ( ) ) ;
2010-08-27 01:01:44 +00:00
return true ;
}
else
{
2011-05-17 03:51:29 +00:00
const char * error_cstr = jit_error . AsCString ( ) ;
if ( error_cstr & & error_cstr [ 0 ] )
error_stream . Printf ( " error: %s \n " , error_cstr ) ;
else
2011-09-20 21:44:10 +00:00
error_stream . Printf ( " error: expression can't be interpreted or run \n " ) ;
2010-08-27 01:01:44 +00:00
return false ;
}
}
2013-04-18 22:06:33 +00:00
static lldb : : addr_t
2013-11-04 09:33:30 +00:00
GetObjectPointer ( lldb : : StackFrameSP frame_sp ,
2013-04-18 22:06:33 +00:00
ConstString & object_name ,
Error & err )
{
err . Clear ( ) ;
if ( ! frame_sp )
{
err . SetErrorStringWithFormat ( " Couldn't load '%s' because the context is incomplete " , object_name . AsCString ( ) ) ;
return LLDB_INVALID_ADDRESS ;
}
lldb : : VariableSP var_sp ;
lldb : : ValueObjectSP valobj_sp ;
valobj_sp = frame_sp - > GetValueForVariableExpressionPath ( object_name . AsCString ( ) ,
lldb : : eNoDynamicValues ,
2013-11-04 09:33:30 +00:00
StackFrame : : eExpressionPathOptionCheckPtrVsMember | |
StackFrame : : eExpressionPathOptionsAllowDirectIVarAccess | |
StackFrame : : eExpressionPathOptionsNoFragileObjcIvar | |
StackFrame : : eExpressionPathOptionsNoSyntheticChildren | |
StackFrame : : eExpressionPathOptionsNoSyntheticArrayRange ,
2013-04-18 22:06:33 +00:00
var_sp ,
err ) ;
if ( ! err . Success ( ) )
return LLDB_INVALID_ADDRESS ;
lldb : : addr_t ret = valobj_sp - > GetValueAsUnsigned ( LLDB_INVALID_ADDRESS ) ;
if ( ret = = LLDB_INVALID_ADDRESS )
{
err . SetErrorStringWithFormat ( " Couldn't load '%s' because its value couldn't be evaluated " , object_name . AsCString ( ) ) ;
return LLDB_INVALID_ADDRESS ;
}
return ret ;
}
2010-08-27 01:01:44 +00:00
bool
2010-10-14 23:45:03 +00:00
ClangUserExpression : : PrepareToExecuteJITExpression ( Stream & error_stream ,
2010-10-19 23:57:21 +00:00
ExecutionContext & exe_ctx ,
lldb : : addr_t & struct_address ,
2010-12-14 00:42:36 +00:00
lldb : : addr_t & object_ptr ,
lldb : : addr_t & cmd_ptr )
2010-08-27 01:01:44 +00:00
{
2012-02-10 01:22:05 +00:00
lldb : : TargetSP target ;
lldb : : ProcessSP process ;
2013-11-04 09:33:30 +00:00
lldb : : StackFrameSP frame ;
2012-02-10 01:22:05 +00:00
if ( ! LockAndCheckContext ( exe_ctx ,
target ,
process ,
frame ) )
{
2013-04-19 07:09:15 +00:00
error_stream . Printf ( " The context has changed before we could JIT the expression! \n " ) ;
2012-02-10 01:22:05 +00:00
return false ;
}
2013-04-18 22:06:33 +00:00
if ( m_jit_start_addr ! = LLDB_INVALID_ADDRESS | | m_can_interpret )
{
2010-12-13 22:46:15 +00:00
if ( m_needs_object_ptr )
2010-09-21 00:44:12 +00:00
{
2010-12-13 22:46:15 +00:00
ConstString object_name ;
if ( m_cplusplus )
{
object_name . SetCString ( " this " ) ;
}
else if ( m_objectivec )
{
object_name . SetCString ( " self " ) ;
}
else
{
error_stream . Printf ( " Need object pointer but don't know the language \n " ) ;
return false ;
}
2013-04-18 22:06:33 +00:00
Error object_ptr_error ;
object_ptr = GetObjectPointer ( frame , object_name , object_ptr_error ) ;
if ( ! object_ptr_error . Success ( ) )
2010-12-13 22:46:15 +00:00
{
2013-04-18 22:06:33 +00:00
error_stream . Printf ( " warning: couldn't get required object pointer (substituting NULL): %s \n " , object_ptr_error . AsCString ( ) ) ;
2011-12-13 01:42:04 +00:00
object_ptr = 0 ;
2010-12-13 22:46:15 +00:00
}
2010-12-14 00:42:36 +00:00
if ( m_objectivec )
{
ConstString cmd_name ( " _cmd " ) ;
2013-04-18 22:06:33 +00:00
cmd_ptr = GetObjectPointer ( frame , cmd_name , object_ptr_error ) ;
if ( ! object_ptr_error . Success ( ) )
2010-12-14 00:42:36 +00:00
{
2013-04-18 22:06:33 +00:00
error_stream . Printf ( " warning: couldn't get cmd pointer (substituting NULL): %s \n " , object_ptr_error . AsCString ( ) ) ;
2011-12-13 01:42:04 +00:00
cmd_ptr = 0 ;
2010-12-14 00:42:36 +00:00
}
}
2010-09-21 00:44:12 +00:00
}
2013-04-18 22:06:33 +00:00
2013-04-27 02:19:33 +00:00
if ( m_materialized_address = = LLDB_INVALID_ADDRESS )
2013-04-18 22:06:33 +00:00
{
2013-04-27 02:19:33 +00:00
Error alloc_error ;
IRMemoryMap : : AllocationPolicy policy = m_can_interpret ? IRMemoryMap : : eAllocationPolicyHostOnly : IRMemoryMap : : eAllocationPolicyMirror ;
m_materialized_address = m_execution_unit_ap - > Malloc ( m_materializer_ap - > GetStructByteSize ( ) ,
m_materializer_ap - > GetStructAlignment ( ) ,
lldb : : ePermissionsReadable | lldb : : ePermissionsWritable ,
policy ,
alloc_error ) ;
if ( ! alloc_error . Success ( ) )
{
error_stream . Printf ( " Couldn't allocate space for materialized struct: %s \n " , alloc_error . AsCString ( ) ) ;
return false ;
}
2013-04-18 22:06:33 +00:00
}
2013-04-27 02:19:33 +00:00
struct_address = m_materialized_address ;
2013-04-18 22:06:33 +00:00
2013-04-27 02:19:33 +00:00
if ( m_can_interpret & & m_stack_frame_bottom = = LLDB_INVALID_ADDRESS )
{
Error alloc_error ;
const size_t stack_frame_size = 512 * 1024 ;
m_stack_frame_bottom = m_execution_unit_ap - > Malloc ( stack_frame_size ,
8 ,
lldb : : ePermissionsReadable | lldb : : ePermissionsWritable ,
IRMemoryMap : : eAllocationPolicyHostOnly ,
alloc_error ) ;
m_stack_frame_top = m_stack_frame_bottom + stack_frame_size ;
if ( ! alloc_error . Success ( ) )
{
error_stream . Printf ( " Couldn't allocate space for the stack frame: %s \n " , alloc_error . AsCString ( ) ) ;
return false ;
}
}
2013-04-18 22:06:33 +00:00
Error materialize_error ;
m_dematerializer_sp = m_materializer_ap - > Materialize ( frame , * m_execution_unit_ap , struct_address , materialize_error ) ;
if ( ! materialize_error . Success ( ) )
2010-08-27 01:01:44 +00:00
{
2010-09-21 00:44:12 +00:00
error_stream . Printf ( " Couldn't materialize struct: %s \n " , materialize_error . AsCString ( ) ) ;
2010-08-27 01:01:44 +00:00
return false ;
}
2010-10-14 23:45:03 +00:00
}
return true ;
}
bool
ClangUserExpression : : FinalizeJITExecution ( Stream & error_stream ,
ExecutionContext & exe_ctx ,
2011-05-09 22:04:36 +00:00
lldb : : ClangExpressionVariableSP & result ,
2013-04-27 02:19:33 +00:00
lldb : : addr_t function_stack_bottom ,
lldb : : addr_t function_stack_top )
2010-10-14 23:45:03 +00:00
{
2013-03-27 23:08:40 +00:00
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2010-12-07 10:00:20 +00:00
if ( log )
2010-12-07 22:55:01 +00:00
log - > Printf ( " -- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution -- " ) ;
2013-04-27 02:19:33 +00:00
2013-04-18 22:06:33 +00:00
if ( ! m_dematerializer_sp )
{
2013-07-12 23:35:21 +00:00
error_stream . Printf ( " Couldn't apply expression side effects : no dematerializer is present " ) ;
2013-04-18 22:06:33 +00:00
return false ;
}
Error dematerialize_error ;
2013-04-27 02:19:33 +00:00
m_dematerializer_sp - > Dematerialize ( dematerialize_error , result , function_stack_bottom , function_stack_top ) ;
2013-04-18 22:06:33 +00:00
if ( ! dematerialize_error . Success ( ) )
2010-10-14 23:45:03 +00:00
{
2013-07-12 23:35:21 +00:00
error_stream . Printf ( " Couldn't apply expression side effects : %s \n " , dematerialize_error . AsCString ( " unknown error " ) ) ;
2010-10-14 23:45:03 +00:00
return false ;
}
2013-04-18 22:06:33 +00:00
2012-01-06 00:35:38 +00:00
if ( result )
result - > TransferAddress ( ) ;
2013-04-18 22:06:33 +00:00
m_dematerializer_sp . reset ( ) ;
2010-10-14 23:45:03 +00:00
return true ;
}
2011-03-24 21:19:54 +00:00
ExecutionResults
2010-10-14 23:45:03 +00:00
ClangUserExpression : : Execute ( Stream & error_stream ,
ExecutionContext & exe_ctx ,
2013-11-04 19:35:17 +00:00
const EvaluateExpressionOptions & options ,
2010-11-30 02:22:11 +00:00
ClangUserExpression : : ClangUserExpressionSP & shared_ptr_to_me ,
2013-11-04 19:35:17 +00:00
lldb : : ClangExpressionVariableSP & result )
2010-10-14 23:45:03 +00:00
{
2011-01-18 22:20:08 +00:00
// The expression log is quite verbose, and if you're just tracking the execution of the
// expression, it's quite convenient to have these logs come out with the STEP log as well.
2013-03-27 23:08:40 +00:00
Log * log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP ) ) ;
2010-12-07 10:00:20 +00:00
2013-04-18 22:06:33 +00:00
if ( m_jit_start_addr ! = LLDB_INVALID_ADDRESS | | m_can_interpret )
2010-10-14 23:45:03 +00:00
{
2012-10-12 17:34:26 +00:00
lldb : : addr_t struct_address = LLDB_INVALID_ADDRESS ;
2010-10-14 23:45:03 +00:00
2011-07-19 19:48:13 +00:00
lldb : : addr_t object_ptr = 0 ;
lldb : : addr_t cmd_ptr = 0 ;
2010-10-14 23:45:03 +00:00
2012-08-18 04:24:00 +00:00
if ( ! PrepareToExecuteJITExpression ( error_stream , exe_ctx , struct_address , object_ptr , cmd_ptr ) )
{
2012-08-18 04:14:54 +00:00
error_stream . Printf ( " Errored out in %s, couldn't PrepareToExecuteJITExpression " , __FUNCTION__ ) ;
2011-03-24 21:19:54 +00:00
return eExecutionSetupError ;
2012-08-18 04:14:54 +00:00
}
2010-08-27 01:01:44 +00:00
2013-04-27 02:19:33 +00:00
lldb : : addr_t function_stack_bottom = LLDB_INVALID_ADDRESS ;
lldb : : addr_t function_stack_top = LLDB_INVALID_ADDRESS ;
2010-08-27 01:01:44 +00:00
2013-04-18 22:06:33 +00:00
if ( m_can_interpret )
{
llvm : : Module * module = m_execution_unit_ap - > GetModule ( ) ;
llvm : : Function * function = m_execution_unit_ap - > GetFunction ( ) ;
2011-11-08 03:00:11 +00:00
2013-04-18 22:06:33 +00:00
if ( ! module | | ! function )
2011-05-17 01:10:11 +00:00
{
2013-04-18 22:06:33 +00:00
error_stream . Printf ( " Supposed to interpret, but nothing is there " ) ;
return eExecutionSetupError ;
2011-05-17 01:10:11 +00:00
}
2010-11-30 02:22:11 +00:00
2013-04-18 22:06:33 +00:00
Error interpreter_error ;
llvm : : SmallVector < lldb : : addr_t , 3 > args ;
if ( m_needs_object_ptr )
{
args . push_back ( object_ptr ) ;
if ( m_objectivec )
args . push_back ( cmd_ptr ) ;
}
args . push_back ( struct_address ) ;
2013-04-27 02:19:33 +00:00
function_stack_bottom = m_stack_frame_bottom ;
function_stack_top = m_stack_frame_top ;
2013-04-18 22:06:33 +00:00
IRInterpreter : : Interpret ( * module ,
* function ,
args ,
* m_execution_unit_ap . get ( ) ,
2013-04-27 02:19:33 +00:00
interpreter_error ,
function_stack_bottom ,
function_stack_top ) ;
2013-04-18 22:06:33 +00:00
if ( ! interpreter_error . Success ( ) )
{
error_stream . Printf ( " Supposed to interpret, but failed: %s " , interpreter_error . AsCString ( ) ) ;
return eExecutionDiscarded ;
}
2010-11-30 02:22:11 +00:00
}
2013-04-18 22:06:33 +00:00
else
2010-11-30 02:22:11 +00:00
{
2013-04-18 22:06:33 +00:00
Address wrapper_address ( m_jit_start_addr ) ;
2013-11-08 01:14:26 +00:00
llvm : : SmallVector < lldb : : addr_t , 3 > args ;
if ( m_needs_object_ptr ) {
args . push_back ( object_ptr ) ;
if ( m_objectivec )
args . push_back ( cmd_ptr ) ;
}
args . push_back ( struct_address ) ;
2013-04-18 22:06:33 +00:00
lldb : : ThreadPlanSP call_plan_sp ( new ThreadPlanCallUserExpression ( exe_ctx . GetThreadRef ( ) ,
wrapper_address ,
2013-11-08 01:14:26 +00:00
args ,
2013-11-07 00:11:47 +00:00
options ,
2013-04-18 22:06:33 +00:00
shared_ptr_to_me ) ) ;
if ( ! call_plan_sp | | ! call_plan_sp - > ValidatePlan ( & error_stream ) )
return eExecutionSetupError ;
2013-04-27 02:19:33 +00:00
lldb : : addr_t function_stack_pointer = static_cast < ThreadPlanCallFunction * > ( call_plan_sp . get ( ) ) - > GetFunctionStackPointer ( ) ;
2013-04-18 22:06:33 +00:00
2013-04-27 02:19:33 +00:00
function_stack_bottom = function_stack_pointer - Host : : GetPageSize ( ) ;
function_stack_top = function_stack_pointer ;
2013-04-18 22:06:33 +00:00
if ( log )
log - > Printf ( " -- [ClangUserExpression::Execute] Execution of expression begins -- " ) ;
if ( exe_ctx . GetProcessPtr ( ) )
exe_ctx . GetProcessPtr ( ) - > SetRunningUserExpression ( true ) ;
ExecutionResults execution_result = exe_ctx . GetProcessRef ( ) . RunThreadPlan ( exe_ctx ,
2013-11-07 00:11:47 +00:00
call_plan_sp ,
options ,
2013-04-18 22:06:33 +00:00
error_stream ) ;
if ( exe_ctx . GetProcessPtr ( ) )
exe_ctx . GetProcessPtr ( ) - > SetRunningUserExpression ( false ) ;
if ( log )
log - > Printf ( " -- [ClangUserExpression::Execute] Execution of expression completed -- " ) ;
if ( execution_result = = eExecutionInterrupted | | execution_result = = eExecutionHitBreakpoint )
{
const char * error_desc = NULL ;
if ( call_plan_sp )
{
lldb : : StopInfoSP real_stop_info_sp = call_plan_sp - > GetRealStopInfo ( ) ;
if ( real_stop_info_sp )
error_desc = real_stop_info_sp - > GetDescription ( ) ;
}
if ( error_desc )
error_stream . Printf ( " Execution was interrupted, reason: %s. " , error_desc ) ;
else
2013-11-07 00:11:47 +00:00
error_stream . PutCString ( " Execution was interrupted. " ) ;
2013-04-18 22:06:33 +00:00
2013-11-07 00:11:47 +00:00
if ( ( execution_result = = eExecutionInterrupted & & options . DoesUnwindOnError ( ) )
| | ( execution_result = = eExecutionHitBreakpoint & & options . DoesIgnoreBreakpoints ( ) ) )
error_stream . PutCString ( " \n The process has been returned to the state before expression evaluation. " ) ;
2013-04-18 22:06:33 +00:00
else
2013-11-07 00:11:47 +00:00
error_stream . PutCString ( " \n The process has been left at the point where it was interrupted, use \" thread return -x \" to return to the state before expression evaluation. " ) ;
2013-04-18 22:06:33 +00:00
return execution_result ;
}
2013-11-07 00:11:47 +00:00
else if ( execution_result = = eExecutionStoppedForDebug )
{
error_stream . PutCString ( " Execution was halted at the first instruction of the expression function because \" debug \" was requested. \n "
" Use \" thread return -x \" to return to the state before expression evaluation. " ) ;
return execution_result ;
}
2013-04-18 22:06:33 +00:00
else if ( execution_result ! = eExecutionCompleted )
{
error_stream . Printf ( " Couldn't execute function; result was %s \n " , Process : : ExecutionResultAsCString ( execution_result ) ) ;
return execution_result ;
}
2010-08-27 01:01:44 +00:00
}
2013-04-27 02:19:33 +00:00
if ( FinalizeJITExecution ( error_stream , exe_ctx , result , function_stack_bottom , function_stack_top ) )
{
2011-03-24 21:19:54 +00:00
return eExecutionCompleted ;
2013-04-27 02:19:33 +00:00
}
2010-11-30 02:22:11 +00:00
else
2012-08-18 04:24:00 +00:00
{
2011-03-24 21:19:54 +00:00
return eExecutionSetupError ;
2012-08-18 04:24:00 +00:00
}
2010-08-27 01:01:44 +00:00
}
else
{
2011-09-15 02:13:07 +00:00
error_stream . Printf ( " Expression can't be run, because there is no JIT compiled function " ) ;
2011-03-24 21:19:54 +00:00
return eExecutionSetupError ;
2010-08-27 01:01:44 +00:00
}
}
2011-03-24 21:19:54 +00:00
ExecutionResults
2011-09-15 02:13:07 +00:00
ClangUserExpression : : Evaluate ( ExecutionContext & exe_ctx ,
2013-11-04 19:35:17 +00:00
const EvaluateExpressionOptions & options ,
2010-10-29 00:29:03 +00:00
const char * expr_cstr ,
2010-11-30 02:22:11 +00:00
const char * expr_prefix ,
2012-07-16 23:10:35 +00:00
lldb : : ValueObjectSP & result_valobj_sp ,
2013-11-04 19:35:17 +00:00
Error & error )
2010-10-05 00:31:29 +00:00
{
2013-03-27 23:08:40 +00:00
Log * log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP ) ) ;
2010-12-07 22:55:01 +00:00
2013-11-04 19:35:17 +00:00
lldb_private : : ExecutionPolicy execution_policy = options . GetExecutionPolicy ( ) ;
const lldb : : LanguageType language = options . GetLanguage ( ) ;
const ResultType desired_type = options . DoesCoerceToId ( ) ? ClangUserExpression : : eResultTypeId : ClangUserExpression : : eResultTypeAny ;
2011-03-24 21:19:54 +00:00
ExecutionResults execution_results = eExecutionSetupError ;
2010-11-04 01:54:29 +00:00
2011-09-22 04:58:26 +00:00
Process * process = exe_ctx . GetProcessPtr ( ) ;
if ( process = = NULL | | process - > GetState ( ) ! = lldb : : eStateStopped )
2010-11-30 02:22:11 +00:00
{
2011-09-15 02:13:07 +00:00
if ( execution_policy = = eExecutionPolicyAlways )
{
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Expression may not run, but is not constant == " ) ;
2010-11-30 02:22:11 +00:00
2011-09-15 02:13:07 +00:00
error . SetErrorString ( " expression needed to run but couldn't " ) ;
return execution_results ;
}
2010-11-30 02:22:11 +00:00
}
2011-09-15 17:43:00 +00:00
2011-09-22 04:58:26 +00:00
if ( process = = NULL | | ! process - > CanJIT ( ) )
2011-09-15 17:43:00 +00:00
execution_policy = eExecutionPolicyNever ;
2010-11-04 01:54:29 +00:00
2011-12-21 22:22:58 +00:00
ClangUserExpressionSP user_expression_sp ( new ClangUserExpression ( expr_cstr , expr_prefix , language , desired_type ) ) ;
2010-11-30 02:22:11 +00:00
2010-10-05 00:31:29 +00:00
StreamString error_stream ;
2011-05-07 01:06:41 +00:00
2010-12-07 22:55:01 +00:00
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Parsing expression %s == " , expr_cstr ) ;
2011-09-15 02:13:07 +00:00
const bool keep_expression_in_memory = true ;
2011-12-21 22:22:58 +00:00
if ( ! user_expression_sp - > Parse ( error_stream , exe_ctx , execution_policy , keep_expression_in_memory ) )
2010-10-05 00:31:29 +00:00
{
if ( error_stream . GetString ( ) . empty ( ) )
error . SetErrorString ( " expression failed to parse, unknown error " ) ;
else
error . SetErrorString ( error_stream . GetString ( ) . c_str ( ) ) ;
}
else
{
2010-12-14 02:59:59 +00:00
lldb : : ClangExpressionVariableSP expr_result ;
2010-10-05 00:31:29 +00:00
2013-04-18 22:06:33 +00:00
if ( execution_policy = = eExecutionPolicyNever & &
! user_expression_sp - > CanInterpret ( ) )
2011-09-15 02:13:07 +00:00
{
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Expression may not run, but is not constant == " ) ;
if ( error_stream . GetString ( ) . empty ( ) )
error . SetErrorString ( " expression needed to run but couldn't " ) ;
}
2010-12-16 03:17:46 +00:00
else
{
error_stream . GetString ( ) . clear ( ) ;
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Executing expression == " ) ;
execution_results = user_expression_sp - > Execute ( error_stream ,
2013-11-04 19:35:17 +00:00
exe_ctx ,
options ,
user_expression_sp ,
expr_result ) ;
2010-12-16 03:17:46 +00:00
2011-03-24 21:19:54 +00:00
if ( execution_results ! = eExecutionCompleted )
2010-10-05 00:31:29 +00:00
{
2010-12-07 22:55:01 +00:00
if ( log )
2010-12-16 03:17:46 +00:00
log - > Printf ( " == [ClangUserExpression::Evaluate] Execution completed abnormally == " ) ;
if ( error_stream . GetString ( ) . empty ( ) )
error . SetErrorString ( " expression failed to execute, unknown error " ) ;
else
error . SetErrorString ( error_stream . GetString ( ) . c_str ( ) ) ;
2010-10-05 00:31:29 +00:00
}
2010-12-16 03:17:46 +00:00
else
2010-10-05 00:31:29 +00:00
{
2010-12-16 03:17:46 +00:00
if ( expr_result )
{
result_valobj_sp = expr_result - > GetValueObject ( ) ;
if ( log )
2011-03-31 00:19:25 +00:00
log - > Printf ( " == [ClangUserExpression::Evaluate] Execution completed normally with result %s == " , result_valobj_sp - > GetValueAsCString ( ) ) ;
2010-12-16 03:17:46 +00:00
}
else
{
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Execution completed normally with no result == " ) ;
2011-08-23 21:20:51 +00:00
error . SetError ( ClangUserExpression : : kNoResult , lldb : : eErrorTypeGeneric ) ;
2010-12-16 03:17:46 +00:00
}
2010-10-05 00:31:29 +00:00
}
}
}
2010-10-19 20:15:00 +00:00
2010-10-05 03:13:51 +00:00
if ( result_valobj_sp . get ( ) = = NULL )
2013-12-10 23:16:40 +00:00
{
result_valobj_sp = ValueObjectConstResult : : Create ( exe_ctx . GetBestExecutionContextScope ( ) , error ) ;
}
2010-10-05 03:13:51 +00:00
2010-11-30 02:22:11 +00:00
return execution_results ;
2010-10-29 20:19:44 +00:00
}