Made expressions that are just casts of pointer
variables be evaluated statically. Also fixed a bug that caused the results of statically-evaluated expressions to be materialized improperly. This bug also removes some duplicate code. llvm-svn: 131042
This commit is contained in:
parent
95496b1856
commit
63697e5025
|
@ -126,6 +126,28 @@ public:
|
|||
lldb_private::TypeFromParser type,
|
||||
const llvm::APInt& value);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// [Used by IRForTarget] Cast an existing variable given a Decl and
|
||||
/// a type.
|
||||
///
|
||||
/// @param[in] name
|
||||
/// The name of the new variable
|
||||
///
|
||||
/// @param[in] decl
|
||||
/// The Clang variable declaration for the original variable,
|
||||
/// which must be looked up in the map
|
||||
///
|
||||
/// @param[in] type
|
||||
/// The desired type of the variable after casting
|
||||
///
|
||||
/// @return
|
||||
/// The created variable
|
||||
//------------------------------------------------------------------
|
||||
lldb::ClangExpressionVariableSP
|
||||
BuildCastVariable (const ConstString &name,
|
||||
clang::VarDecl *decl,
|
||||
lldb_private::TypeFromParser type);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// [Used by IRForTarget] Add a variable to the list of persistent
|
||||
/// variables for the process.
|
||||
|
@ -620,7 +642,7 @@ private:
|
|||
/// @return
|
||||
/// The LLDB Variable found, or NULL if none was found.
|
||||
//------------------------------------------------------------------
|
||||
Variable *
|
||||
lldb::VariableSP
|
||||
FindVariableInScope (StackFrame &frame,
|
||||
const ConstString &name,
|
||||
TypeFromUser *type = NULL);
|
||||
|
@ -656,7 +678,7 @@ private:
|
|||
//------------------------------------------------------------------
|
||||
Value *
|
||||
GetVariableValue (ExecutionContext &exe_ctx,
|
||||
Variable *var,
|
||||
lldb::VariableSP var,
|
||||
clang::ASTContext *parser_ast_context,
|
||||
TypeFromUser *found_type = NULL,
|
||||
TypeFromParser *parser_type = NULL);
|
||||
|
@ -673,7 +695,7 @@ private:
|
|||
//------------------------------------------------------------------
|
||||
void
|
||||
AddOneVariable (NameSearchContext &context,
|
||||
Variable *var);
|
||||
lldb::VariableSP var);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Use the NameSearchContext to generate a Decl for the given
|
||||
|
|
|
@ -103,9 +103,13 @@ public:
|
|||
/// The execution context to write the function into.
|
||||
///
|
||||
/// @param[out] const_result
|
||||
/// If non-NULL, the result of the expression is constant, and the
|
||||
/// If the result of the expression is constant, and the
|
||||
/// expression has no side effects, this is set to the result of the
|
||||
/// expression.
|
||||
/// expression.
|
||||
///
|
||||
/// @param[in] jit_only_if_needed
|
||||
/// True if the expression must be compiled, regardless of whether a
|
||||
/// constant result could be extracted from the IR or no.
|
||||
///
|
||||
/// @return
|
||||
/// An error code indicating the success or failure of the operation.
|
||||
|
@ -116,7 +120,8 @@ public:
|
|||
lldb::addr_t &func_addr,
|
||||
lldb::addr_t &func_end,
|
||||
ExecutionContext &exe_ctx,
|
||||
lldb::ClangExpressionVariableSP *const_result = NULL);
|
||||
lldb::ClangExpressionVariableSP &const_result,
|
||||
bool jit_only_if_needed = false);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Disassemble the machine code for a JITted function from the target
|
||||
|
|
|
@ -97,7 +97,8 @@ public:
|
|||
m_parser_type(),
|
||||
m_named_decl (NULL),
|
||||
m_llvm_value (NULL),
|
||||
m_lldb_value (NULL)
|
||||
m_lldb_value (NULL),
|
||||
m_lldb_var ()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -105,6 +106,7 @@ public:
|
|||
const clang::NamedDecl *m_named_decl; ///< The Decl corresponding to this variable
|
||||
llvm::Value *m_llvm_value; ///< The IR value corresponding to this variable; usually a GlobalValue
|
||||
lldb_private::Value *m_lldb_value; ///< The value found in LLDB for this variable
|
||||
lldb::VariableSP m_lldb_var; ///< The original variable for this variable
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (ParserVars);
|
||||
|
|
|
@ -85,11 +85,6 @@ public:
|
|||
/// True if the resulting persistent variable should reside in
|
||||
/// target memory, if applicable.
|
||||
///
|
||||
/// @param[out] const_result
|
||||
/// If this is non-NULL, the expression has no side effects, and
|
||||
/// the expression returns a constant result, then that result
|
||||
/// is put into this variable.
|
||||
///
|
||||
/// @return
|
||||
/// True on success (no errors); false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
|
@ -97,8 +92,7 @@ public:
|
|||
Parse (Stream &error_stream,
|
||||
ExecutionContext &exe_ctx,
|
||||
TypeFromUser desired_type,
|
||||
bool keep_result_in_memory,
|
||||
lldb::ClangExpressionVariableSP *const_result = NULL);
|
||||
bool keep_result_in_memory);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Execute the parsed expression
|
||||
|
@ -133,7 +127,6 @@ public:
|
|||
Execute (Stream &error_stream,
|
||||
ExecutionContext &exe_ctx,
|
||||
bool discard_on_error,
|
||||
bool keep_in_memory,
|
||||
ClangUserExpressionSP &shared_ptr_to_me,
|
||||
lldb::ClangExpressionVariableSP &result);
|
||||
|
||||
|
@ -244,10 +237,6 @@ public:
|
|||
/// True if the thread's state should be restored in the case
|
||||
/// of an error.
|
||||
///
|
||||
/// @param[in] keep_in_memory
|
||||
/// True if the resulting persistent variable should reside in
|
||||
/// target memory, if applicable.
|
||||
///
|
||||
/// @param[in] expr_cstr
|
||||
/// A C string containing the expression to be evaluated.
|
||||
///
|
||||
|
@ -264,7 +253,6 @@ public:
|
|||
static ExecutionResults
|
||||
Evaluate (ExecutionContext &exe_ctx,
|
||||
bool discard_on_error,
|
||||
bool keep_in_memory,
|
||||
const char *expr_cstr,
|
||||
const char *expr_prefix,
|
||||
lldb::ValueObjectSP &result_valobj_sp);
|
||||
|
@ -289,13 +277,15 @@ private:
|
|||
TypeFromUser m_desired_type; ///< The type to coerce the expression's result to. If NULL, inferred from the expression.
|
||||
|
||||
std::auto_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing and materializing the expression.
|
||||
std::auto_ptr<ClangExpressionVariableList> m_local_variables; ///< The local expression variables, if the expression is DWARF.
|
||||
std::auto_ptr<ClangExpressionVariableList> m_local_variables; ///< The local expression variables, if the expression is DWARF.
|
||||
std::auto_ptr<StreamString> m_dwarf_opcodes; ///< The DWARF opcodes for the expression. May be NULL.
|
||||
|
||||
bool m_cplusplus; ///< True if the expression is compiled as a C++ member function (true if it was parsed when exe_ctx was in a C++ method).
|
||||
bool m_objectivec; ///< True if the expression is compiled as an Objective-C method (true if it was parsed when exe_ctx was in an Objective-C method).
|
||||
bool m_needs_object_ptr; ///< True if "this" or "self" must be looked up and passed in. False if the expression doesn't really use them and they can be NULL.
|
||||
bool m_const_object; ///< True if "this" is const.
|
||||
|
||||
lldb::ClangExpressionVariableSP m_const_result; ///< The statically-computed result of the expression. NULL if it could not be computed statically or the expression has side effects.
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
|
|
@ -21,9 +21,11 @@ namespace llvm {
|
|||
class CallInst;
|
||||
class Constant;
|
||||
class Function;
|
||||
class GlobalValue;
|
||||
class GlobalVariable;
|
||||
class Instruction;
|
||||
class Module;
|
||||
class StoreInst;
|
||||
class Value;
|
||||
}
|
||||
|
||||
|
@ -62,10 +64,9 @@ public:
|
|||
/// are resolved.
|
||||
///
|
||||
/// @param[in] const_result
|
||||
/// If non-NULL, a shared pointer to a ClangExpressionVariable that
|
||||
/// is populated with the statically-computed result of the function,
|
||||
/// if it has no side-effects and the result can be computed
|
||||
/// statically.
|
||||
/// This variable is populated with the statically-computed result
|
||||
/// of the function, if it has no side-effects and the result can
|
||||
/// be computed statically.
|
||||
///
|
||||
/// @param[in] error_stream
|
||||
/// If non-NULL, a stream on which errors can be printed.
|
||||
|
@ -75,7 +76,7 @@ public:
|
|||
//------------------------------------------------------------------
|
||||
IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map,
|
||||
bool resolve_vars,
|
||||
lldb::ClangExpressionVariableSP *const_result,
|
||||
lldb::ClangExpressionVariableSP &const_result,
|
||||
lldb_private::Stream *error_stream,
|
||||
const char* func_name = "$__lldb_expr");
|
||||
|
||||
|
@ -148,6 +149,24 @@ private:
|
|||
/// Also see ASTResultSynthesizer.
|
||||
//------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Set the constant result variable m_const_result to the provided
|
||||
/// constant, assuming it can be evaluated. The result variable
|
||||
/// will be reset to NULL later if the expression has side effects.
|
||||
///
|
||||
/// @param[in] llvm_module
|
||||
/// The module currently being processed.
|
||||
///
|
||||
/// @param[in] global
|
||||
/// The global entity to search for
|
||||
///
|
||||
/// @return
|
||||
/// The corresponding variable declaration
|
||||
//------------------------------------------------------------------
|
||||
clang::NamedDecl *
|
||||
DeclForGlobal (llvm::Module &llvm_module,
|
||||
llvm::GlobalValue *global);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Set the constant result variable m_const_result to the provided
|
||||
/// constant, assuming it can be evaluated. The result variable
|
||||
|
@ -161,15 +180,27 @@ private:
|
|||
///
|
||||
/// @param[in] type
|
||||
/// The Clang type of the result variable.
|
||||
///
|
||||
/// @return
|
||||
/// True on success; false otherwise
|
||||
//------------------------------------------------------------------
|
||||
void
|
||||
MaybeSetConstantResult (llvm::Constant *initializer,
|
||||
const lldb_private::ConstString &name,
|
||||
lldb_private::TypeFromParser type);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// If the IR represents a cast of a variable, set m_const_result
|
||||
/// to the result of the cast. The result variable will be reset to
|
||||
/// NULL latger if the expression has side effects.
|
||||
///
|
||||
/// @param[in] llvm_module
|
||||
/// The module currently being processed.
|
||||
///
|
||||
/// @param[in] type
|
||||
/// The Clang type of the result variable.
|
||||
//------------------------------------------------------------------
|
||||
void
|
||||
MaybeSetCastResult (llvm::Module &llvm_module,
|
||||
lldb_private::TypeFromParser type);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// The top-level pass implementation
|
||||
///
|
||||
|
@ -476,10 +507,11 @@ private:
|
|||
lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The DeclMap containing the Decls
|
||||
llvm::Constant *m_CFStringCreateWithBytes; ///< The address of the function CFStringCreateWithBytes, cast to the appropriate function pointer type
|
||||
llvm::Constant *m_sel_registerName; ///< The address of the function sel_registerName, cast to the appropriate function pointer type
|
||||
lldb::ClangExpressionVariableSP *m_const_result; ///< If non-NULL, this value should be set to the return value of the expression if it is constant and the expression has no side effects
|
||||
lldb::ClangExpressionVariableSP &m_const_result; ///< This value should be set to the return value of the expression if it is constant and the expression has no side effects
|
||||
lldb_private::Stream *m_error_stream; ///< If non-NULL, the stream on which errors should be printed
|
||||
|
||||
bool m_has_side_effects; ///< True if the function's result cannot be simply determined statically
|
||||
llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that writes to the result variable. If m_has_side_effects is true, this is NULL.
|
||||
bool m_result_is_pointer; ///< True if the function's result in the AST is a pointer (see comments in ASTResultSynthesizer::SynthesizeBodyResult)
|
||||
|
||||
private:
|
||||
|
|
|
@ -139,7 +139,7 @@ ClangExpressionDeclMap::BuildIntegerVariable (const ConstString &name,
|
|||
type.GetASTContext(),
|
||||
type.GetOpaqueQualType()),
|
||||
context);
|
||||
|
||||
|
||||
if (!m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx->GetBestExecutionContextScope (),
|
||||
name,
|
||||
user_type,
|
||||
|
@ -194,10 +194,81 @@ ClangExpressionDeclMap::BuildIntegerVariable (const ConstString &name,
|
|||
}
|
||||
|
||||
pvar_sp->m_flags |= ClangExpressionVariable::EVIsFreezeDried;
|
||||
pvar_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
|
||||
pvar_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
|
||||
|
||||
return pvar_sp;
|
||||
}
|
||||
|
||||
lldb::ClangExpressionVariableSP
|
||||
ClangExpressionDeclMap::BuildCastVariable (const ConstString &name,
|
||||
clang::VarDecl *decl,
|
||||
lldb_private::TypeFromParser type)
|
||||
{
|
||||
assert (m_parser_vars.get());
|
||||
|
||||
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
||||
|
||||
ExecutionContext *exe_ctx = m_parser_vars->m_exe_ctx;
|
||||
clang::ASTContext *context(exe_ctx->target->GetScratchClangASTContext()->getASTContext());
|
||||
|
||||
ClangExpressionVariableSP var_sp (m_found_entities.GetVariable(decl));
|
||||
|
||||
if (!var_sp)
|
||||
var_sp = m_parser_vars->m_persistent_vars->GetVariable(decl);
|
||||
|
||||
if (!var_sp)
|
||||
return ClangExpressionVariableSP();
|
||||
|
||||
TypeFromUser user_type(ClangASTContext::CopyType(context,
|
||||
type.GetASTContext(),
|
||||
type.GetOpaqueQualType()),
|
||||
context);
|
||||
|
||||
TypeFromUser var_type = var_sp->GetTypeFromUser();
|
||||
|
||||
VariableSP var = FindVariableInScope (*exe_ctx->frame, var_sp->GetName(), &var_type);
|
||||
|
||||
if (!var)
|
||||
return lldb::ClangExpressionVariableSP(); // but we should handle this; it may be a persistent variable
|
||||
|
||||
ValueObjectSP var_valobj = exe_ctx->frame->GetValueObjectForFrameVariable(var, lldb::eNoDynamicValues);
|
||||
|
||||
if (!var_valobj)
|
||||
return lldb::ClangExpressionVariableSP();
|
||||
|
||||
ValueObjectSP var_casted_valobj = var_valobj->CastPointerType(name.GetCString(), user_type);
|
||||
|
||||
if (!var_casted_valobj)
|
||||
return lldb::ClangExpressionVariableSP();
|
||||
|
||||
if (log)
|
||||
{
|
||||
StreamString my_stream_string;
|
||||
|
||||
ClangASTType::DumpTypeDescription (var_type.GetASTContext(),
|
||||
var_type.GetOpaqueQualType(),
|
||||
&my_stream_string);
|
||||
|
||||
|
||||
log->Printf("Building cast variable to type: %s", my_stream_string.GetString().c_str());
|
||||
}
|
||||
|
||||
ClangExpressionVariableSP pvar_sp = m_parser_vars->m_persistent_vars->CreatePersistentVariable (var_casted_valobj);
|
||||
|
||||
if (!pvar_sp)
|
||||
return lldb::ClangExpressionVariableSP();
|
||||
|
||||
if (pvar_sp != m_parser_vars->m_persistent_vars->GetVariable(name))
|
||||
return lldb::ClangExpressionVariableSP();
|
||||
|
||||
pvar_sp->m_flags |= ClangExpressionVariable::EVIsFreezeDried;
|
||||
pvar_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
|
||||
pvar_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
|
||||
|
||||
return pvar_sp;
|
||||
}
|
||||
|
||||
bool
|
||||
ClangExpressionDeclMap::AddPersistentVariable
|
||||
(
|
||||
|
@ -535,9 +606,9 @@ ClangExpressionDeclMap::GetObjectPointer
|
|||
return false;
|
||||
}
|
||||
|
||||
Variable *object_ptr_var = FindVariableInScope (*exe_ctx.frame,
|
||||
object_name,
|
||||
(suppress_type_check ? NULL : &m_struct_vars->m_object_pointer_type));
|
||||
VariableSP object_ptr_var = FindVariableInScope (*exe_ctx.frame,
|
||||
object_name,
|
||||
(suppress_type_check ? NULL : &m_struct_vars->m_object_pointer_type));
|
||||
|
||||
if (!object_ptr_var)
|
||||
{
|
||||
|
@ -1122,7 +1193,7 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
|
|||
if (log)
|
||||
log->Printf("Materialized %s into 0x%llx", var_sp->GetName().GetCString(), (uint64_t)mem);
|
||||
}
|
||||
else if (!var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference)
|
||||
else if (!(var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference))
|
||||
{
|
||||
err.SetErrorStringWithFormat("Persistent variables without separate allocations are not currently supported.");
|
||||
return false;
|
||||
|
@ -1153,7 +1224,7 @@ ClangExpressionDeclMap::DoMaterializeOneVariable
|
|||
const ConstString &name(expr_var->GetName());
|
||||
TypeFromUser type(expr_var->GetTypeFromUser());
|
||||
|
||||
Variable *var = FindVariableInScope (*exe_ctx.frame, name, &type);
|
||||
VariableSP var = FindVariableInScope (*exe_ctx.frame, name, &type);
|
||||
|
||||
if (!var)
|
||||
{
|
||||
|
@ -1495,7 +1566,7 @@ ClangExpressionDeclMap::DoMaterializeOneRegister
|
|||
return true;
|
||||
}
|
||||
|
||||
Variable *
|
||||
lldb::VariableSP
|
||||
ClangExpressionDeclMap::FindVariableInScope
|
||||
(
|
||||
StackFrame &frame,
|
||||
|
@ -1508,7 +1579,7 @@ ClangExpressionDeclMap::FindVariableInScope
|
|||
VariableList *var_list = frame.GetVariableList(true);
|
||||
|
||||
if (!var_list)
|
||||
return NULL;
|
||||
return lldb::VariableSP();
|
||||
|
||||
lldb::VariableSP var_sp (var_list->FindVariable(name));
|
||||
|
||||
|
@ -1543,17 +1614,17 @@ ClangExpressionDeclMap::FindVariableInScope
|
|||
if (type->GetASTContext() == var_sp->GetType()->GetClangAST())
|
||||
{
|
||||
if (!ClangASTContext::AreTypesSame(type->GetASTContext(), type->GetOpaqueQualType(), var_sp->GetType()->GetClangFullType()))
|
||||
return NULL;
|
||||
return lldb::VariableSP();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (log)
|
||||
log->PutCString("Skipping a candidate variable because of different AST contexts");
|
||||
return NULL;
|
||||
return lldb::VariableSP();
|
||||
}
|
||||
}
|
||||
|
||||
return var_sp.get();
|
||||
return var_sp;
|
||||
}
|
||||
|
||||
// Interface for ClangASTSource
|
||||
|
@ -1590,7 +1661,7 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
|
|||
// doesn't start with our phony prefix of '$'
|
||||
if (name_unique_cstr[0] != '$')
|
||||
{
|
||||
Variable *var = FindVariableInScope(*m_parser_vars->m_exe_ctx->frame, name);
|
||||
VariableSP var = FindVariableInScope(*m_parser_vars->m_exe_ctx->frame, name);
|
||||
|
||||
// If we found a variable in scope, no need to pull up function names
|
||||
if (var != NULL)
|
||||
|
@ -1797,7 +1868,7 @@ Value *
|
|||
ClangExpressionDeclMap::GetVariableValue
|
||||
(
|
||||
ExecutionContext &exe_ctx,
|
||||
Variable *var,
|
||||
VariableSP var,
|
||||
clang::ASTContext *parser_ast_context,
|
||||
TypeFromUser *user_type,
|
||||
TypeFromParser *parser_type
|
||||
|
@ -1904,7 +1975,7 @@ ClangExpressionDeclMap::GetVariableValue
|
|||
}
|
||||
|
||||
void
|
||||
ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, Variable* var)
|
||||
ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP var)
|
||||
{
|
||||
assert (m_parser_vars.get());
|
||||
|
||||
|
@ -1936,6 +2007,7 @@ ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, Variable* va
|
|||
entity->m_parser_vars->m_named_decl = var_decl;
|
||||
entity->m_parser_vars->m_llvm_value = NULL;
|
||||
entity->m_parser_vars->m_lldb_value = var_location;
|
||||
entity->m_parser_vars->m_lldb_var = var;
|
||||
|
||||
if (log)
|
||||
{
|
||||
|
|
|
@ -456,7 +456,8 @@ ClangExpressionParser::MakeJIT (lldb::addr_t &func_allocation_addr,
|
|||
lldb::addr_t &func_addr,
|
||||
lldb::addr_t &func_end,
|
||||
ExecutionContext &exe_ctx,
|
||||
lldb::ClangExpressionVariableSP *const_result)
|
||||
lldb::ClangExpressionVariableSP &const_result,
|
||||
bool jit_only_if_needed)
|
||||
{
|
||||
func_allocation_addr = LLDB_INVALID_ADDRESS;
|
||||
func_addr = LLDB_INVALID_ADDRESS;
|
||||
|
@ -512,6 +513,12 @@ ClangExpressionParser::MakeJIT (lldb::addr_t &func_allocation_addr,
|
|||
return err;
|
||||
}
|
||||
|
||||
if (jit_only_if_needed && const_result.get())
|
||||
{
|
||||
err.Clear();
|
||||
return err;
|
||||
}
|
||||
|
||||
if (m_expr.NeedsValidation() && exe_ctx.process->GetDynamicCheckers())
|
||||
{
|
||||
IRDynamicChecks ir_dynamic_checks(*exe_ctx.process->GetDynamicCheckers(), function_name.c_str());
|
||||
|
|
|
@ -251,7 +251,9 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
|
|||
if (m_JITted)
|
||||
return true;
|
||||
|
||||
Error jit_error (m_parser->MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx));
|
||||
lldb::ClangExpressionVariableSP const_result;
|
||||
|
||||
Error jit_error (m_parser->MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, const_result));
|
||||
|
||||
if (!jit_error.Success())
|
||||
return false;
|
||||
|
|
|
@ -49,7 +49,8 @@ ClangUserExpression::ClangUserExpression (const char *expr,
|
|||
m_cplusplus (false),
|
||||
m_objectivec (false),
|
||||
m_needs_object_ptr (false),
|
||||
m_const_object (false)
|
||||
m_const_object (false),
|
||||
m_const_result ()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -147,8 +148,7 @@ bool
|
|||
ClangUserExpression::Parse (Stream &error_stream,
|
||||
ExecutionContext &exe_ctx,
|
||||
TypeFromUser desired_type,
|
||||
bool keep_result_in_memory,
|
||||
lldb::ClangExpressionVariableSP *const_result)
|
||||
bool keep_result_in_memory)
|
||||
{
|
||||
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
||||
|
||||
|
@ -284,7 +284,7 @@ ClangUserExpression::Parse (Stream &error_stream,
|
|||
|
||||
m_dwarf_opcodes.reset();
|
||||
|
||||
Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, const_result);
|
||||
Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, m_const_result, true);
|
||||
|
||||
m_expr_decl_map->DidParse();
|
||||
|
||||
|
@ -457,7 +457,6 @@ ExecutionResults
|
|||
ClangUserExpression::Execute (Stream &error_stream,
|
||||
ExecutionContext &exe_ctx,
|
||||
bool discard_on_error,
|
||||
bool keep_in_memory,
|
||||
ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
|
||||
lldb::ClangExpressionVariableSP &result)
|
||||
{
|
||||
|
@ -556,7 +555,6 @@ ClangUserExpression::DwarfOpcodeStream ()
|
|||
ExecutionResults
|
||||
ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
|
||||
bool discard_on_error,
|
||||
bool keep_in_memory,
|
||||
const char *expr_cstr,
|
||||
const char *expr_prefix,
|
||||
lldb::ValueObjectSP &result_valobj_sp)
|
||||
|
@ -603,13 +601,11 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
|
|||
ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix));
|
||||
|
||||
StreamString error_stream;
|
||||
|
||||
lldb::ClangExpressionVariableSP const_result;
|
||||
|
||||
|
||||
if (log)
|
||||
log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
|
||||
|
||||
if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), &const_result))
|
||||
if (!user_expression_sp->Parse (error_stream, exe_ctx, TypeFromUser(NULL, NULL), true))
|
||||
{
|
||||
if (error_stream.GetString().empty())
|
||||
error.SetErrorString ("expression failed to parse, unknown error");
|
||||
|
@ -620,12 +616,12 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
|
|||
{
|
||||
lldb::ClangExpressionVariableSP expr_result;
|
||||
|
||||
if (const_result.get() && !keep_in_memory)
|
||||
if (user_expression_sp->m_const_result.get())
|
||||
{
|
||||
if (log)
|
||||
log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant ==");
|
||||
|
||||
result_valobj_sp = const_result->GetValueObject();
|
||||
result_valobj_sp = user_expression_sp->m_const_result->GetValueObject();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -637,7 +633,6 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
|
|||
execution_results = user_expression_sp->Execute (error_stream,
|
||||
exe_ctx,
|
||||
discard_on_error,
|
||||
keep_in_memory,
|
||||
user_expression_sp,
|
||||
expr_result);
|
||||
|
||||
|
|
|
@ -108,8 +108,10 @@ ClangUtilityFunction::Install (Stream &error_stream,
|
|||
//////////////////////////////////
|
||||
// JIT the output of the parser
|
||||
//
|
||||
|
||||
lldb::ClangExpressionVariableSP const_result;
|
||||
|
||||
Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx);
|
||||
Error jit_error = parser.MakeJIT (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, const_result);
|
||||
|
||||
if (exe_ctx.process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
|
||||
m_jit_process_sp = exe_ctx.process->GetSP();
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "lldb/Core/Scalar.h"
|
||||
#include "lldb/Core/StreamString.h"
|
||||
#include "lldb/Expression/ClangExpressionDeclMap.h"
|
||||
#include "lldb/Symbol/ClangASTContext.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
|
@ -35,7 +36,7 @@ static char ID;
|
|||
|
||||
IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
|
||||
bool resolve_vars,
|
||||
lldb::ClangExpressionVariableSP *const_result,
|
||||
lldb::ClangExpressionVariableSP &const_result,
|
||||
lldb_private::Stream *error_stream,
|
||||
const char *func_name) :
|
||||
ModulePass(ID),
|
||||
|
@ -44,10 +45,11 @@ IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
|
|||
m_decl_map(decl_map),
|
||||
m_CFStringCreateWithBytes(NULL),
|
||||
m_sel_registerName(NULL),
|
||||
m_const_result(const_result),
|
||||
m_error_stream(error_stream),
|
||||
m_has_side_effects(false),
|
||||
m_result_is_pointer(false)
|
||||
m_result_store(NULL),
|
||||
m_result_is_pointer(false),
|
||||
m_const_result(const_result)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -87,7 +89,7 @@ IRForTarget::HasSideEffects (llvm::Module &llvm_module,
|
|||
{
|
||||
llvm::Function::iterator bbi;
|
||||
BasicBlock::iterator ii;
|
||||
|
||||
|
||||
for (bbi = llvm_function.begin();
|
||||
bbi != llvm_function.end();
|
||||
++bbi)
|
||||
|
@ -108,15 +110,33 @@ IRForTarget::HasSideEffects (llvm::Module &llvm_module,
|
|||
|
||||
Value *store_ptr = store_inst->getPointerOperand();
|
||||
|
||||
if (!isa <AllocaInst> (store_ptr))
|
||||
return true;
|
||||
else
|
||||
std::string ptr_name;
|
||||
|
||||
if (store_ptr->hasName())
|
||||
ptr_name = store_ptr->getNameStr();
|
||||
|
||||
if (isa <AllocaInst> (store_ptr))
|
||||
break;
|
||||
|
||||
if (ptr_name.find("$__lldb_expr_result") != std::string::npos)
|
||||
{
|
||||
if (ptr_name.find("GV") == std::string::npos)
|
||||
m_result_store = store_inst;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case Instruction::Load:
|
||||
case Instruction::Alloca:
|
||||
case Instruction::GetElementPtr:
|
||||
case Instruction::BitCast:
|
||||
case Instruction::Ret:
|
||||
case Instruction::ICmp:
|
||||
case Instruction::Br:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -125,18 +145,133 @@ IRForTarget::HasSideEffects (llvm::Module &llvm_module,
|
|||
return false;
|
||||
}
|
||||
|
||||
clang::NamedDecl *
|
||||
IRForTarget::DeclForGlobal (llvm::Module &module, GlobalValue *global_val)
|
||||
{
|
||||
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
||||
|
||||
NamedMDNode *named_metadata = module.getNamedMetadata("clang.global.decl.ptrs");
|
||||
|
||||
if (!named_metadata)
|
||||
return NULL;
|
||||
|
||||
unsigned num_nodes = named_metadata->getNumOperands();
|
||||
unsigned node_index;
|
||||
|
||||
for (node_index = 0;
|
||||
node_index < num_nodes;
|
||||
++node_index)
|
||||
{
|
||||
MDNode *metadata_node = named_metadata->getOperand(node_index);
|
||||
|
||||
if (!metadata_node)
|
||||
return NULL;
|
||||
|
||||
if (metadata_node->getNumOperands() != 2)
|
||||
continue;
|
||||
|
||||
if (metadata_node->getOperand(0) != global_val)
|
||||
continue;
|
||||
|
||||
ConstantInt *constant_int = dyn_cast<ConstantInt>(metadata_node->getOperand(1));
|
||||
|
||||
if (!constant_int)
|
||||
return NULL;
|
||||
|
||||
uintptr_t ptr = constant_int->getZExtValue();
|
||||
|
||||
return reinterpret_cast<clang::NamedDecl *>(ptr);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
IRForTarget::MaybeSetConstantResult (llvm::Constant *initializer,
|
||||
const lldb_private::ConstString &name,
|
||||
lldb_private::TypeFromParser type)
|
||||
{
|
||||
if (!m_const_result)
|
||||
if (llvm::ConstantExpr *init_expr = dyn_cast<llvm::ConstantExpr>(initializer))
|
||||
{
|
||||
switch (init_expr->getOpcode())
|
||||
{
|
||||
default:
|
||||
return;
|
||||
case Instruction::IntToPtr:
|
||||
MaybeSetConstantResult (init_expr->getOperand(0), name, type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (llvm::ConstantInt *init_int = dyn_cast<llvm::ConstantInt>(initializer))
|
||||
{
|
||||
m_const_result = m_decl_map->BuildIntegerVariable(name, type, init_int->getValue());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IRForTarget::MaybeSetCastResult (llvm::Module &llvm_module, lldb_private::TypeFromParser type)
|
||||
{
|
||||
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
||||
|
||||
if (!m_result_store)
|
||||
return;
|
||||
|
||||
if (llvm::ConstantInt *init_int = dyn_cast<llvm::ConstantInt>(initializer))
|
||||
LoadInst *original_load = NULL;
|
||||
|
||||
for (llvm::Value *current_value = m_result_store->getValueOperand(), *next_value;
|
||||
current_value != NULL;
|
||||
current_value = next_value)
|
||||
{
|
||||
*m_const_result = m_decl_map->BuildIntegerVariable(name, type, init_int->getValue());
|
||||
CastInst *cast_inst = dyn_cast<CastInst>(current_value);
|
||||
LoadInst *load_inst = dyn_cast<LoadInst>(current_value);
|
||||
|
||||
if (cast_inst)
|
||||
{
|
||||
next_value = cast_inst->getOperand(0);
|
||||
}
|
||||
else if(load_inst)
|
||||
{
|
||||
if (isa<LoadInst>(load_inst->getPointerOperand()))
|
||||
{
|
||||
next_value = load_inst->getPointerOperand();
|
||||
}
|
||||
else
|
||||
{
|
||||
original_load = load_inst;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Value *loaded_value = original_load->getPointerOperand();
|
||||
GlobalVariable *loaded_global = dyn_cast<GlobalVariable>(loaded_value);
|
||||
|
||||
if (!loaded_global)
|
||||
return;
|
||||
|
||||
clang::NamedDecl *loaded_decl = DeclForGlobal(llvm_module, loaded_global);
|
||||
|
||||
if (!loaded_decl)
|
||||
return;
|
||||
|
||||
clang::VarDecl *loaded_var = dyn_cast<clang::VarDecl>(loaded_decl);
|
||||
|
||||
if (!loaded_var)
|
||||
return;
|
||||
|
||||
if (log)
|
||||
{
|
||||
lldb_private::StreamString type_desc_stream;
|
||||
type.DumpTypeDescription(&type_desc_stream);
|
||||
|
||||
log->Printf("Type to cast variable to: \"%s\"", type_desc_stream.GetString().c_str());
|
||||
}
|
||||
|
||||
m_const_result = m_decl_map->BuildCastVariable(m_result_name, loaded_var, type);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -214,64 +349,50 @@ IRForTarget::CreateResultVariable (llvm::Module &llvm_module, llvm::Function &ll
|
|||
return false;
|
||||
}
|
||||
|
||||
// Find the metadata and follow it to the VarDecl
|
||||
|
||||
NamedMDNode *named_metadata = llvm_module.getNamedMetadata("clang.global.decl.ptrs");
|
||||
|
||||
if (!named_metadata)
|
||||
clang::NamedDecl *result_decl = DeclForGlobal (llvm_module, result_global);
|
||||
if (!result_decl)
|
||||
{
|
||||
if (log)
|
||||
log->PutCString("No global metadata");
|
||||
log->PutCString("Result variable doesn't have a corresponding Decl");
|
||||
|
||||
if (m_error_stream)
|
||||
m_error_stream->Printf("Internal error [IRForTarget]: No metadata\n");
|
||||
m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) does not have a corresponding Clang entity\n", result_name);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned num_nodes = named_metadata->getNumOperands();
|
||||
unsigned node_index;
|
||||
|
||||
MDNode *metadata_node = NULL;
|
||||
|
||||
for (node_index = 0;
|
||||
node_index < num_nodes;
|
||||
++node_index)
|
||||
if (log)
|
||||
{
|
||||
metadata_node = named_metadata->getOperand(node_index);
|
||||
std::string decl_desc_str;
|
||||
raw_string_ostream decl_desc_stream(decl_desc_str);
|
||||
result_decl->print(decl_desc_stream);
|
||||
decl_desc_stream.flush();
|
||||
|
||||
if (metadata_node->getNumOperands() != 2)
|
||||
continue;
|
||||
|
||||
if (metadata_node->getOperand(0) == result_global)
|
||||
break;
|
||||
log->Printf("Found result decl: \"%s\"", decl_desc_str.c_str());
|
||||
}
|
||||
|
||||
if (!metadata_node)
|
||||
clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl);
|
||||
if (!result_var)
|
||||
{
|
||||
if (log)
|
||||
log->PutCString("Couldn't find result metadata");
|
||||
log->PutCString("Result variable Decl isn't a VarDecl");
|
||||
|
||||
if (m_error_stream)
|
||||
m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) is a global variable, but has no metadata\n", result_name);
|
||||
m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s)'s corresponding Clang entity isn't a variable\n", result_name);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ConstantInt *constant_int = dyn_cast<ConstantInt>(metadata_node->getOperand(1));
|
||||
|
||||
lldb::addr_t result_decl_intptr = constant_int->getZExtValue();
|
||||
|
||||
clang::VarDecl *result_decl = reinterpret_cast<clang::VarDecl *>(result_decl_intptr);
|
||||
|
||||
// Get the next available result name from m_decl_map and create the persistent
|
||||
// variable for it
|
||||
|
||||
lldb_private::TypeFromParser result_decl_type;
|
||||
|
||||
// If the result is an Lvalue, it is emitted as a pointer; see
|
||||
// ASTResultSynthesizer::SynthesizeBodyResult.
|
||||
if (m_result_is_pointer)
|
||||
{
|
||||
clang::QualType pointer_qual_type = result_decl->getType();
|
||||
clang::QualType pointer_qual_type = result_var->getType();
|
||||
const clang::Type *pointer_type = pointer_qual_type.getTypePtr();
|
||||
const clang::PointerType *pointer_pointertype = dyn_cast<clang::PointerType>(pointer_type);
|
||||
|
||||
|
@ -293,18 +414,19 @@ IRForTarget::CreateResultVariable (llvm::Module &llvm_module, llvm::Function &ll
|
|||
}
|
||||
else
|
||||
{
|
||||
result_decl_type = lldb_private::TypeFromParser(result_decl->getType().getAsOpaquePtr(),
|
||||
result_decl_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(),
|
||||
&result_decl->getASTContext());
|
||||
}
|
||||
|
||||
if (log)
|
||||
{
|
||||
lldb_private::StreamString type_desc_stream;
|
||||
result_decl_type.DumpTypeDescription(&type_desc_stream);
|
||||
|
||||
log->Printf("Result decl type: \"%s\"", type_desc_stream.GetString().c_str());
|
||||
}
|
||||
|
||||
m_result_name = m_decl_map->GetPersistentResultName();
|
||||
// If the result is an Lvalue, it is emitted as a pointer; see
|
||||
// ASTResultSynthesizer::SynthesizeBodyResult.
|
||||
m_decl_map->AddPersistentVariable(result_decl,
|
||||
m_result_name,
|
||||
result_decl_type,
|
||||
true,
|
||||
m_result_is_pointer);
|
||||
|
||||
if (log)
|
||||
log->Printf("Creating a new result global: \"%s\"", m_result_name.GetCString());
|
||||
|
@ -325,8 +447,8 @@ IRForTarget::CreateResultVariable (llvm::Module &llvm_module, llvm::Function &ll
|
|||
// ClangExpressionDeclMap::DoMaterialize, and the name of the variable is
|
||||
// fixed up.
|
||||
|
||||
ConstantInt *new_constant_int = ConstantInt::get(constant_int->getType(),
|
||||
result_decl_intptr,
|
||||
ConstantInt *new_constant_int = ConstantInt::get(llvm::Type::getInt64Ty(llvm_module.getContext()),
|
||||
reinterpret_cast<uint64_t>(result_decl),
|
||||
false);
|
||||
|
||||
llvm::Value* values[2];
|
||||
|
@ -334,6 +456,7 @@ IRForTarget::CreateResultVariable (llvm::Module &llvm_module, llvm::Function &ll
|
|||
values[1] = new_constant_int;
|
||||
|
||||
MDNode *persistent_global_md = MDNode::get(llvm_module.getContext(), values, 2);
|
||||
NamedMDNode *named_metadata = llvm_module.getNamedMetadata("clang.global.decl.ptrs");
|
||||
named_metadata->addOperand(persistent_global_md);
|
||||
|
||||
if (log)
|
||||
|
@ -384,8 +507,20 @@ IRForTarget::CreateResultVariable (llvm::Module &llvm_module, llvm::Function &ll
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!m_has_side_effects && lldb_private::ClangASTContext::IsPointerType (result_decl_type.GetOpaqueQualType()))
|
||||
{
|
||||
MaybeSetCastResult (llvm_module, result_decl_type);
|
||||
}
|
||||
|
||||
result_global->replaceAllUsesWith(new_result_global);
|
||||
}
|
||||
|
||||
if (!m_const_result)
|
||||
m_decl_map->AddPersistentVariable(result_decl,
|
||||
m_result_name,
|
||||
result_decl_type,
|
||||
true,
|
||||
m_result_is_pointer);
|
||||
|
||||
result_global->eraseFromParent();
|
||||
|
||||
|
@ -1047,45 +1182,6 @@ IRForTarget::RewritePersistentAllocs(llvm::Module &llvm_module, llvm::BasicBlock
|
|||
return true;
|
||||
}
|
||||
|
||||
static clang::NamedDecl *
|
||||
DeclForGlobalValue(Module &module, GlobalValue *global_value)
|
||||
{
|
||||
NamedMDNode *named_metadata = module.getNamedMetadata("clang.global.decl.ptrs");
|
||||
|
||||
if (!named_metadata)
|
||||
return NULL;
|
||||
|
||||
unsigned num_nodes = named_metadata->getNumOperands();
|
||||
unsigned node_index;
|
||||
|
||||
for (node_index = 0;
|
||||
node_index < num_nodes;
|
||||
++node_index)
|
||||
{
|
||||
MDNode *metadata_node = named_metadata->getOperand(node_index);
|
||||
|
||||
if (!metadata_node)
|
||||
return NULL;
|
||||
|
||||
if (metadata_node->getNumOperands() != 2)
|
||||
continue;
|
||||
|
||||
if (metadata_node->getOperand(0) != global_value)
|
||||
continue;
|
||||
|
||||
ConstantInt *constant_int = dyn_cast<ConstantInt>(metadata_node->getOperand(1));
|
||||
|
||||
if (!constant_int)
|
||||
return NULL;
|
||||
|
||||
uintptr_t ptr = constant_int->getZExtValue();
|
||||
|
||||
return reinterpret_cast<clang::NamedDecl *>(ptr);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// This function does not report errors; its callers are responsible.
|
||||
bool
|
||||
IRForTarget::MaybeHandleVariable (Module &llvm_module, Value *llvm_value_ptr)
|
||||
|
@ -1110,7 +1206,7 @@ IRForTarget::MaybeHandleVariable (Module &llvm_module, Value *llvm_value_ptr)
|
|||
}
|
||||
else if (GlobalVariable *global_variable = dyn_cast<GlobalVariable>(llvm_value_ptr))
|
||||
{
|
||||
clang::NamedDecl *named_decl = DeclForGlobalValue(llvm_module, global_variable);
|
||||
clang::NamedDecl *named_decl = DeclForGlobal(llvm_module, global_variable);
|
||||
|
||||
if (!named_decl)
|
||||
{
|
||||
|
@ -1331,7 +1427,7 @@ IRForTarget::MaybeHandleCall (Module &llvm_module, CallInst *llvm_call_inst)
|
|||
str.SetCStringWithLength (fun->getName().data(), fun->getName().size());
|
||||
}
|
||||
|
||||
clang::NamedDecl *fun_decl = DeclForGlobalValue (llvm_module, fun);
|
||||
clang::NamedDecl *fun_decl = DeclForGlobal (llvm_module, fun);
|
||||
lldb::addr_t fun_addr = LLDB_INVALID_ADDRESS;
|
||||
Value **fun_value_ptr = NULL;
|
||||
|
||||
|
@ -1445,7 +1541,7 @@ IRForTarget::ResolveExternals (Module &llvm_module, Function &llvm_function)
|
|||
if (log)
|
||||
log->Printf("Examining %s, DeclForGlobalValue returns %p",
|
||||
(*global).getName().str().c_str(),
|
||||
DeclForGlobalValue(llvm_module, global));
|
||||
DeclForGlobal(llvm_module, global));
|
||||
|
||||
if ((*global).getName().str().find("OBJC_IVAR") == 0)
|
||||
{
|
||||
|
@ -1457,7 +1553,7 @@ IRForTarget::ResolveExternals (Module &llvm_module, Function &llvm_function)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
else if (DeclForGlobalValue(llvm_module, global))
|
||||
else if (DeclForGlobal(llvm_module, global))
|
||||
{
|
||||
if (!MaybeHandleVariable (llvm_module, global))
|
||||
{
|
||||
|
@ -1882,6 +1978,9 @@ IRForTarget::runOnModule (Module &llvm_module)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (m_const_result)
|
||||
return true;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Fix all Objective-C constant strings to use NSStringWithCString:encoding:
|
||||
//
|
||||
|
|
|
@ -1246,14 +1246,13 @@ Process::LoadImage (const FileSpec &image_spec, Error &error)
|
|||
ExecutionContext exe_ctx;
|
||||
frame_sp->CalculateExecutionContext (exe_ctx);
|
||||
bool unwind_on_error = true;
|
||||
bool keep_in_memory = false;
|
||||
StreamString expr;
|
||||
char path[PATH_MAX];
|
||||
image_spec.GetPath(path, sizeof(path));
|
||||
expr.Printf("dlopen (\"%s\", 2)", path);
|
||||
const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n";
|
||||
lldb::ValueObjectSP result_valobj_sp;
|
||||
ClangUserExpression::Evaluate (exe_ctx, keep_in_memory, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
|
||||
ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
|
||||
if (result_valobj_sp->GetError().Success())
|
||||
{
|
||||
Scalar scalar;
|
||||
|
@ -1314,12 +1313,11 @@ Process::UnloadImage (uint32_t image_token)
|
|||
ExecutionContext exe_ctx;
|
||||
frame_sp->CalculateExecutionContext (exe_ctx);
|
||||
bool unwind_on_error = true;
|
||||
bool keep_in_memory = false;
|
||||
StreamString expr;
|
||||
expr.Printf("dlclose ((void *)0x%llx)", image_addr);
|
||||
const char *prefix = "extern \"C\" int dlclose(void* handle);\n";
|
||||
lldb::ValueObjectSP result_valobj_sp;
|
||||
ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, keep_in_memory, expr.GetData(), prefix, result_valobj_sp);
|
||||
ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
|
||||
if (result_valobj_sp->GetError().Success())
|
||||
{
|
||||
Scalar scalar;
|
||||
|
|
|
@ -994,7 +994,6 @@ Target::EvaluateExpression
|
|||
|
||||
execution_results = ClangUserExpression::Evaluate (exe_ctx,
|
||||
unwind_on_error,
|
||||
keep_in_memory,
|
||||
expr_cstr,
|
||||
prefix,
|
||||
result_valobj_sp);
|
||||
|
|
Loading…
Reference in New Issue