Extended the IR interpreter to handle the variables

"_cmd", "this", and "self".  These variables are handled
differently from all other external variables used by
the expression.  Other variables are used indirectly
through the $__lldb_arg operand; only _cmd, this, and
self are passed directly through the ABI.

There are two modifications:

 - I added a function to ClangExpressionDeclMap that
   retrives the value of one of these variables by name;
   and

 - I made IRInterpreter fetch these values when needed,
   and ensured that the proper level of indirection is
   used.

llvm-svn: 143065
This commit is contained in:
Sean Callanan 2011-10-26 21:20:00 +00:00
parent b3285224cd
commit d2cb626ac1
3 changed files with 136 additions and 42 deletions

View File

@ -440,6 +440,19 @@ public:
lldb_private::Value
LookupDecl (clang::NamedDecl *decl);
//------------------------------------------------------------------
/// [Used by IRInterpreter] Get the Value for "this", "self", or
/// "_cmd".
///
/// @param[in] name
/// The name of the entity to be found.
///
/// @return
/// The value, or NULL.
//------------------------------------------------------------------
lldb_private::Value
GetSpecialValue (const ConstString &name);
//------------------------------------------------------------------
/// [Used by IRInterpreter] Returns true if the result is a
/// reference to data in the target, meaning it must be

View File

@ -959,7 +959,12 @@ ClangExpressionDeclMap::LookupDecl (clang::NamedDecl *decl)
if (!expr_var_sp->m_parser_vars.get() || !expr_var_sp->m_parser_vars->m_lldb_var)
return Value();
return *GetVariableValue(exe_ctx, expr_var_sp->m_parser_vars->m_lldb_var, NULL);
std::auto_ptr<Value> value(GetVariableValue(exe_ctx, expr_var_sp->m_parser_vars->m_lldb_var, NULL));
if (value.get())
return *value;
else
return Value();
}
else if (persistent_var_sp)
{
@ -969,7 +974,7 @@ ClangExpressionDeclMap::LookupDecl (clang::NamedDecl *decl)
m_parser_vars->m_exe_ctx->GetProcessSP() &&
m_parser_vars->m_exe_ctx->GetProcessSP()->IsAlive())
{
return persistent_var_sp->m_live_sp->GetValue();
return persistent_var_sp->m_live_sp->GetValue();
}
else
{
@ -986,6 +991,39 @@ ClangExpressionDeclMap::LookupDecl (clang::NamedDecl *decl)
}
}
Value
ClangExpressionDeclMap::GetSpecialValue (const ConstString &name)
{
assert(m_parser_vars.get());
if (!m_parser_vars->m_exe_ctx)
return Value();
StackFrame *frame = m_parser_vars->m_exe_ctx->GetFramePtr();
if (!frame)
return Value();
VariableList *vars = frame->GetVariableList(false);
if (!vars)
return Value();
lldb::VariableSP var = vars->FindVariable(name);
if (!var ||
!var->IsInScope(frame) ||
!var->LocationIsValidForFrame (frame))
return Value();
std::auto_ptr<Value> value(GetVariableValue(*m_parser_vars->m_exe_ctx, var, NULL));
if (value.get())
return *value;
else
return Value();
}
// Interface for CommandObjectExpression
bool
@ -1535,8 +1573,8 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
Error allocate_error;
mem = process->AllocateMemory(pvar_byte_size,
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
allocate_error);
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
allocate_error);
if (mem == LLDB_INVALID_ADDRESS)
{
@ -1577,9 +1615,9 @@ ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
// Now write the location of the area into the struct.
Error write_error;
if (!process->WriteScalarToMemory (addr,
var_sp->m_live_sp->GetValue().GetScalar(),
process->GetAddressByteSize(),
write_error))
var_sp->m_live_sp->GetValue().GetScalar(),
process->GetAddressByteSize(),
write_error))
{
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", var_sp->GetName().GetCString(), write_error.AsCString());
return false;

View File

@ -576,6 +576,12 @@ public:
const GlobalValue *global_value = dyn_cast<GlobalValue>(value);
// If the variable is indirected through the argument
// array then we need to build an extra level of indirection
// for it. This is the default; only magic arguments like
// "this", "self", and "_cmd" are direct.
bool indirect_variable = true;
// Attempt to resolve the value using the program's data.
// If it is, the values to be created are:
//
@ -586,17 +592,40 @@ public:
// resides. This is an IR-level variable.
do
{
if (!global_value)
break;
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
lldb_private::Value resolved_value;
clang::NamedDecl *decl = IRForTarget::DeclForGlobal(global_value, &module);
if (!decl)
break;
lldb_private::Value resolved_value = m_decl_map.LookupDecl(decl);
if (global_value)
{
clang::NamedDecl *decl = IRForTarget::DeclForGlobal(global_value, &module);
if (!decl)
break;
if (isa<clang::FunctionDecl>(decl))
{
if (log)
log->Printf("The interpreter does not handle function pointers at the moment");
return Memory::Region();
}
resolved_value = m_decl_map.LookupDecl(decl);
}
else
{
// Special-case "this", "self", and "_cmd"
std::string name_str = value->getNameStr();
if (name_str == "this" ||
name_str == "self" ||
name_str == "_cmd")
resolved_value = m_decl_map.GetSpecialValue(lldb_private::ConstString(name_str.c_str()));
indirect_variable = false;
}
if (resolved_value.GetScalar().GetType() != lldb_private::Scalar::e_void)
{
@ -605,7 +634,10 @@ public:
Memory::Region data_region = m_memory.Malloc(value->getType());
data_region.m_allocation->m_origin = resolved_value;
Memory::Region ref_region = m_memory.Malloc(value->getType());
Memory::Region pointer_region = m_memory.Malloc(value->getType());
Memory::Region pointer_region;
if (indirect_variable)
pointer_region = m_memory.Malloc(value->getType());
if (!Cache(data_region.m_allocation, value->getType()))
return Memory::Region();
@ -613,7 +645,7 @@ public:
if (ref_region.IsInvalid())
return Memory::Region();
if (pointer_region.IsInvalid())
if (pointer_region.IsInvalid() && indirect_variable)
return Memory::Region();
DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region);
@ -621,31 +653,35 @@ public:
if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX)
return Memory::Region();
DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region);
if (pointer_encoder->PutAddress(0, ref_region.m_base) == UINT32_MAX)
return Memory::Region();
m_values[value] = pointer_region;
return pointer_region;
}
else if (isa<clang::FunctionDecl>(decl))
{
if (log)
log->Printf("The interpreter does not handle function pointers at the moment");
return Memory::Region();
if (indirect_variable)
{
DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region);
if (pointer_encoder->PutAddress(0, ref_region.m_base) == UINT32_MAX)
return Memory::Region();
m_values[value] = pointer_region;
return pointer_region;
}
else
{
m_values[value] = ref_region;
return ref_region;
}
}
else
{
Memory::Region data_region = m_memory.Place(value->getType(), resolved_value.GetScalar().ULongLong(), resolved_value);
Memory::Region ref_region = m_memory.Malloc(value->getType());
Memory::Region pointer_region = m_memory.Malloc(value->getType());
Memory::Region pointer_region;
if (indirect_variable)
pointer_region = m_memory.Malloc(value->getType());
if (ref_region.IsInvalid())
return Memory::Region();
if (pointer_region.IsInvalid())
if (pointer_region.IsInvalid() && indirect_variable)
return Memory::Region();
DataEncoderSP ref_encoder = m_memory.GetEncoder(ref_region);
@ -653,23 +689,30 @@ public:
if (ref_encoder->PutAddress(0, data_region.m_base) == UINT32_MAX)
return Memory::Region();
DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region);
if (indirect_variable)
{
DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_region);
if (pointer_encoder->PutAddress(0, ref_region.m_base) == UINT32_MAX)
return Memory::Region();
m_values[value] = pointer_region;
if (pointer_encoder->PutAddress(0, ref_region.m_base) == UINT32_MAX)
return Memory::Region();
m_values[value] = pointer_region;
}
if (log)
{
log->Printf("Made an allocation for %s", PrintValue(global_value).c_str());
log->Printf("Made an allocation for %s", PrintValue(value).c_str());
log->Printf(" Data contents : %s", m_memory.PrintData(data_region.m_base, data_region.m_extent).c_str());
log->Printf(" Data region : %llx", (unsigned long long)data_region.m_base);
log->Printf(" Ref region : %llx", (unsigned long long)ref_region.m_base);
log->Printf(" Pointer region : %llx", (unsigned long long)pointer_region.m_base);
if (indirect_variable)
log->Printf(" Pointer region : %llx", (unsigned long long)pointer_region.m_base);
}
return pointer_region;
if (indirect_variable)
return pointer_region;
else
return ref_region;
}
}
}