diff options
author | Sean Callanan <scallanan@apple.com> | 2011-10-26 21:20:00 +0000 |
---|---|---|
committer | Sean Callanan <scallanan@apple.com> | 2011-10-26 21:20:00 +0000 |
commit | d2cb626ac190b2a3a933c748a082d4eef255a0ae (patch) | |
tree | 059f53132bac02e286723a8e06ed4927726a95f5 | |
parent | b3285224cd90f3ef2cf4254b86dd0ad79ff0dfe1 (diff) | |
download | bcm5719-llvm-d2cb626ac190b2a3a933c748a082d4eef255a0ae.tar.gz bcm5719-llvm-d2cb626ac190b2a3a933c748a082d4eef255a0ae.zip |
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
-rw-r--r-- | lldb/include/lldb/Expression/ClangExpressionDeclMap.h | 13 | ||||
-rw-r--r-- | lldb/source/Expression/ClangExpressionDeclMap.cpp | 52 | ||||
-rw-r--r-- | lldb/source/Expression/IRInterpreter.cpp | 113 |
3 files changed, 136 insertions, 42 deletions
diff --git a/lldb/include/lldb/Expression/ClangExpressionDeclMap.h b/lldb/include/lldb/Expression/ClangExpressionDeclMap.h index 5bbf777160c..670e0149313 100644 --- a/lldb/include/lldb/Expression/ClangExpressionDeclMap.h +++ b/lldb/include/lldb/Expression/ClangExpressionDeclMap.h @@ -441,6 +441,19 @@ public: 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 /// dereferenced once more to get its data. diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp index 10939324897..64dea9cc006 100644 --- a/lldb/source/Expression/ClangExpressionDeclMap.cpp +++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp @@ -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; diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp index 32c5c9097ea..97130d1d39d 100644 --- a/lldb/source/Expression/IRInterpreter.cpp +++ b/lldb/source/Expression/IRInterpreter.cpp @@ -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 (pointer_encoder->PutAddress(0, ref_region.m_base) == UINT32_MAX) - return Memory::Region(); + if (indirect_variable) + { + DataEncoderSP pointer_encoder = m_memory.GetEncoder(pointer_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; } } } |