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:
Sean Callanan 2011-05-07 01:06:41 +00:00
parent 95496b1856
commit 63697e5025
13 changed files with 384 additions and 159 deletions

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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:

View File

@ -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)
{

View File

@ -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());

View File

@ -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;

View File

@ -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);

View File

@ -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();

View File

@ -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:
//

View File

@ -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;

View File

@ -994,7 +994,6 @@ Target::EvaluateExpression
execution_results = ClangUserExpression::Evaluate (exe_ctx,
unwind_on_error,
keep_in_memory,
expr_cstr,
prefix,
result_valobj_sp);