summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/Commands/CommandObjectExpression.cpp81
-rw-r--r--lldb/source/Expression/ClangExpressionDeclMap.cpp91
-rw-r--r--lldb/source/Expression/ClangPersistentVariables.cpp117
-rw-r--r--lldb/source/Expression/IRForTarget.cpp140
4 files changed, 310 insertions, 119 deletions
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index 7d83b2c722b..a9cf2194fd9 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -252,7 +252,7 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream
bool canInterpret = false;
clang::ASTContext *ast_context = clang_expr.GetASTContext ();
- Value expr_result;
+ ClangPersistentVariable *expr_result = 0;
Error expr_error;
canInterpret = clang_expr.ConvertIRToDWARF (expr_local_vars, dwarf_opcodes);
@@ -373,79 +373,32 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream
if (!expr_decl_map.Dematerialize(&m_exe_ctx, expr_result, expr_error))
{
- error_stream.Printf ("Couldn't dematerialize struct: %s\n", expr_error.AsCString("unknown error"));
+ error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
return false;
}
}
-
- ///////////////////////////////////////
- // Interpret the result and print it
- //
-
- lldb::Format format = m_options.format;
-
- // Resolve any values that are possible
- expr_result.ResolveValue (&m_exe_ctx, ast_context);
-
- if (expr_result.GetContextType () == Value::eContextTypeInvalid &&
- expr_result.GetValueType () == Value::eValueTypeScalar &&
- format == eFormatDefault)
- {
- // The expression result is just a scalar with no special formatting
- expr_result.GetScalar ().GetValue (&output_stream, m_options.show_types);
- output_stream.EOL ();
- return true;
- }
-
- // The expression result is more complext and requires special handling
- DataExtractor data;
- expr_error = expr_result.GetValueAsData (&m_exe_ctx, ast_context, data, 0);
-
- if (!expr_error.Success ())
- {
- error_stream.Printf ("error: couldn't resolve result value: %s\n", expr_error.AsCString ());
- return false;
- }
-
- if (format == eFormatDefault)
- format = expr_result.GetValueDefaultFormat ();
-
- void *clang_type = expr_result.GetValueOpaqueClangQualType ();
- if (clang_type)
+ if (expr_result)
{
- if (m_options.show_types)
- output_stream.Printf("(%s) ", ClangASTType::GetClangTypeName (clang_type).GetCString());
+ StreamString ss;
- ClangASTType::DumpValue (ast_context, // The ASTContext that the clang type belongs to
- clang_type, // The opaque clang type we want to dump that value of
- &m_exe_ctx, // The execution context for memory and variable access
- &output_stream, // Stream to dump to
- format, // Format to use when dumping
- data, // A buffer containing the bytes for the clang type
- 0, // Byte offset within "data" where value is
- data.GetByteSize (), // Size in bytes of the value we are dumping
- 0, // Bitfield bit size
- 0, // Bitfield bit offset
- m_options.show_types, // Show types?
- m_options.show_summary, // Show summary?
- m_options.debug, // Debug logging output?
- UINT32_MAX); // Depth to dump in case this is an aggregate type
+ Error err = expr_result->Print (ss,
+ m_exe_ctx,
+ m_options.format,
+ m_options.show_types,
+ m_options.show_summary,
+ m_options.debug);
+
+ if (err.Success())
+ output_stream.PutCString(ss.GetString().c_str());
+ else
+ error_stream.Printf ("Couldn't print result : %s\n", err.AsCString("unknown error"));
}
else
{
- data.Dump (&output_stream, // Stream to dump to
- 0, // Byte offset within "data"
- format, // Format to use when dumping
- data.GetByteSize (), // Size in bytes of each item we are dumping
- 1, // Number of items to dump
- UINT32_MAX, // Number of items per line
- LLDB_INVALID_ADDRESS, // Invalid address, don't show any offset/address context
- 0, // Bitfield bit size
- 0); // Bitfield bit offset
+ error_stream.Printf ("Expression produced no result\n");
}
- output_stream.EOL();
-
+
return true;
}
diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp
index da4333c49c7..fb10605a36f 100644
--- a/lldb/source/Expression/ClangExpressionDeclMap.cpp
+++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp
@@ -83,22 +83,25 @@ ClangExpressionDeclMap::GetIndexForDecl (uint32_t &index,
// Interface for IRForTarget
+void
+ClangExpressionDeclMap::GetPersistentResultName (std::string &name)
+{
+ m_persistent_vars->GetNextResultName(m_result_name);
+
+ name = m_result_name;
+}
+
bool
-ClangExpressionDeclMap::AddPersistentVariable (const clang::NamedDecl *decl)
+ClangExpressionDeclMap::AddPersistentVariable (const char *name, TypeFromParser parser_type)
{
clang::ASTContext *context(m_exe_ctx->target->GetScratchClangASTContext()->getASTContext());
- const clang::VarDecl *var(dyn_cast<clang::VarDecl>(decl));
-
- if (!var)
- return false;
-
TypeFromUser user_type(ClangASTContext::CopyType(context,
- &var->getASTContext(),
- var->getType().getAsOpaquePtr()),
+ parser_type.GetASTContext(),
+ parser_type.GetOpaqueQualType()),
context);
- ConstString const_name(decl->getName().str().c_str());
+ ConstString const_name(name);
ClangPersistentVariable *pvar = m_persistent_vars->CreateVariable(const_name, user_type);
@@ -292,10 +295,10 @@ ClangExpressionDeclMap::Materialize (ExecutionContext *exe_ctx,
bool
ClangExpressionDeclMap::Dematerialize (ExecutionContext *exe_ctx,
- lldb_private::Value &result_value,
+ ClangPersistentVariable *&result,
Error &err)
{
- return DoMaterialize(true, exe_ctx, &result_value, err);
+ return DoMaterialize(true, exe_ctx, &result, err);
}
bool
@@ -366,11 +369,11 @@ ClangExpressionDeclMap::DumpMaterializedStruct(ExecutionContext *exe_ctx,
bool
ClangExpressionDeclMap::DoMaterialize (bool dematerialize,
ExecutionContext *exe_ctx,
- lldb_private::Value *result_value,
+ ClangPersistentVariable **result,
Error &err)
{
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-
+
if (!m_struct_laid_out)
{
err.SetErrorString("Structure hasn't been laid out yet");
@@ -426,35 +429,53 @@ ClangExpressionDeclMap::DoMaterialize (bool dematerialize,
if (!GetIndexForDecl(tuple_index, iter->m_decl))
{
- if (iter->m_name[0] == '$')
- {
- if (!DoMaterializeOnePersistentVariable(dematerialize, *exe_ctx, iter->m_name.c_str(), m_materialized_location + iter->m_offset, err))
- return false;
- }
- else if (iter->m_name.find("___clang_expr_result") != std::string::npos)
+ if (iter->m_name.find("___clang_expr_result") != std::string::npos)
{
- if (log)
- log->Printf("Found special result variable %s", iter->m_name.c_str());
-
if (dematerialize)
{
- clang::ASTContext *context(exe_ctx->target->GetScratchClangASTContext()->getASTContext());
+ // Here we pick up the odd anomaly produced by
+ // IRForTarget::createResultVariable (and described in a comment
+ // there).
+ //
+ // We rename the variable to the name of the result PVar and
+ // incidentally drop the address of the PVar into *result
+ // (if it's non-NULL, of course). We then let this case fall
+ // through to the persistent variable handler.
- if (!context)
- {
- err.SetErrorString("Couldn't find a scratch AST context to put the result type into");
- }
+ if (log)
+ log->PutCString("Found result member in the struct");
- TypeFromUser copied_type(ClangASTContext::CopyType(context,
- iter->m_parser_type.GetASTContext(),
- iter->m_parser_type.GetOpaqueQualType()),
- context);
+ iter->m_name = m_result_name;
- result_value->SetContext(Value::eContextTypeOpaqueClangQualType, copied_type.GetOpaqueQualType());
-
- result_value->SetValueType(Value::eValueTypeLoadAddress);
- result_value->GetScalar() = (uintptr_t)m_materialized_location + iter->m_offset;
+ if (result)
+ {
+ if (log)
+ log->PutCString("Returning result PVar");
+
+ *result = m_persistent_vars->GetVariable(ConstString(m_result_name.c_str()));
+
+ if (!*result)
+ {
+ err.SetErrorStringWithFormat("Couldn't find persistent variable for result %s", m_result_name.c_str());
+ }
+ }
+ else
+ {
+ if (log)
+ log->PutCString("Didn't return result PVar; pointer was NULL");
+ }
}
+ else
+ {
+ // The result variable doesn't need to be materialized, ever.
+ continue;
+ }
+ }
+
+ if (iter->m_name[0] == '$')
+ {
+ if (!DoMaterializeOnePersistentVariable(dematerialize, *exe_ctx, iter->m_name.c_str(), m_materialized_location + iter->m_offset, err))
+ return false;
}
else
{
diff --git a/lldb/source/Expression/ClangPersistentVariables.cpp b/lldb/source/Expression/ClangPersistentVariables.cpp
index dbeac006250..7e1664889cc 100644
--- a/lldb/source/Expression/ClangPersistentVariables.cpp
+++ b/lldb/source/Expression/ClangPersistentVariables.cpp
@@ -8,11 +8,98 @@
//===----------------------------------------------------------------------===//
#include "ClangPersistentVariables.h"
+#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Value.h"
using namespace lldb_private;
-using namespace clang;
+
+Error
+ClangPersistentVariable::Print (Stream &output_stream,
+ ExecutionContext &exe_ctx,
+ lldb::Format format,
+ bool show_types,
+ bool show_summary,
+ bool verbose)
+{
+ Error err;
+
+ Value val;
+
+ clang::ASTContext *ast_context = m_user_type.GetASTContext();
+
+ val.SetContext (Value::eContextTypeOpaqueClangQualType, m_user_type.GetOpaqueQualType ());
+ val.SetValueType (Value::eValueTypeHostAddress);
+ val.GetScalar() = (uint64_t)Data ();
+
+ val.ResolveValue (&exe_ctx, ast_context);
+
+ if (val.GetContextType () == Value::eContextTypeInvalid &&
+ val.GetValueType () == Value::eValueTypeScalar &&
+ format == lldb::eFormatDefault)
+ {
+ // The expression result is just a scalar with no special formatting
+ val.GetScalar ().GetValue (&output_stream, show_types);
+ output_stream.EOL ();
+ return err;
+ }
+
+ // The expression result is more complext and requires special handling
+ DataExtractor data;
+ Error expr_error = val.GetValueAsData (&exe_ctx, ast_context, data, 0);
+
+ if (!expr_error.Success ())
+ {
+ err.SetErrorToGenericError ();
+ err.SetErrorStringWithFormat ("Couldn't resolve result value: %s", expr_error.AsCString ());
+ return err;
+ }
+
+ if (format == lldb::eFormatDefault)
+ format = val.GetValueDefaultFormat ();
+
+ void *clang_type = val.GetValueOpaqueClangQualType ();
+
+ output_stream.Printf("%s = ", m_name.AsCString("<anonymous>"));
+
+ if (clang_type)
+ {
+ if (show_types)
+ output_stream.Printf("(%s) ", ClangASTType::GetClangTypeName (clang_type).GetCString());
+
+ ClangASTType::DumpValue (ast_context, // The ASTContext that the clang type belongs to
+ clang_type, // The opaque clang type we want to dump that value of
+ &exe_ctx, // The execution context for memory and variable access
+ &output_stream, // Stream to dump to
+ format, // Format to use when dumping
+ data, // A buffer containing the bytes for the clang type
+ 0, // Byte offset within "data" where value is
+ data.GetByteSize (), // Size in bytes of the value we are dumping
+ 0, // Bitfield bit size
+ 0, // Bitfield bit offset
+ show_types, // Show types?
+ show_summary, // Show summary?
+ verbose, // Debug logging output?
+ UINT32_MAX); // Depth to dump in case this is an aggregate type
+ }
+ else
+ {
+ data.Dump (&output_stream, // Stream to dump to
+ 0, // Byte offset within "data"
+ format, // Format to use when dumping
+ data.GetByteSize (), // Size in bytes of each item we are dumping
+ 1, // Number of items to dump
+ UINT32_MAX, // Number of items per line
+ LLDB_INVALID_ADDRESS, // Invalid address, don't show any offset/address context
+ 0, // Bitfield bit size
+ 0); // Bitfield bit offset
+ }
+
+ output_stream.EOL();
+
+ return err;
+}
ClangPersistentVariables::ClangPersistentVariables () :
m_variables(),
@@ -24,7 +111,7 @@ ClangPersistentVariable *
ClangPersistentVariables::CreateVariable (ConstString name,
TypeFromUser user_type)
{
- ClangPersistentVariable new_var(user_type);
+ ClangPersistentVariable new_var(name, user_type);
if (m_variables.find(name) != m_variables.end())
return NULL;
@@ -35,21 +122,6 @@ ClangPersistentVariables::CreateVariable (ConstString name,
}
ClangPersistentVariable *
-ClangPersistentVariables::CreateResultVariable (TypeFromUser user_type)
-{
- StreamString s;
- s.Printf("$%llu", m_result_counter);
- ConstString name(s.GetString().c_str());
-
- ClangPersistentVariable *ret = CreateVariable (name, user_type);
-
- if (ret != NULL)
- ++m_result_counter;
-
- return ret;
-}
-
-ClangPersistentVariable *
ClangPersistentVariables::GetVariable (ConstString name)
{
if (m_variables.find(name) == m_variables.end())
@@ -57,3 +129,14 @@ ClangPersistentVariables::GetVariable (ConstString name)
return &m_variables[name];
}
+
+void
+ClangPersistentVariables::GetNextResultName (std::string &name)
+{
+ StreamString s;
+ s.Printf("$%llu", m_result_counter);
+
+ m_result_counter++;
+
+ name = s.GetString();
+}
diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Expression/IRForTarget.cpp
index 9541945eebc..ca1aeb4327c 100644
--- a/lldb/source/Expression/IRForTarget.cpp
+++ b/lldb/source/Expression/IRForTarget.cpp
@@ -14,6 +14,7 @@
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Target/TargetData.h"
+#include "llvm/ValueSymbolTable.h"
#include "clang/AST/ASTContext.h"
@@ -55,6 +56,129 @@ IRForTarget::~IRForTarget()
{
}
+bool
+IRForTarget::createResultVariable(llvm::Module &M,
+ llvm::Function &F)
+{
+ lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+
+ // Find the result variable
+
+ Value *result_value = M.getNamedValue("___clang_expr_result");
+
+ if (!result_value)
+ {
+ if (log)
+ log->PutCString("Couldn't find result variable");
+ return false;
+ }
+
+ if (log)
+ log->Printf("Found result in the IR: %s", PrintValue(result_value, false).c_str());
+
+ GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value);
+
+ if (!result_global)
+ {
+ if (log)
+ log->PutCString("Result variable isn't a GlobalVariable");
+ return false;
+ }
+
+ // Find the metadata and follow it to the VarDecl
+
+ NamedMDNode *named_metadata = M.getNamedMetadata("clang.global.decl.ptrs");
+
+ if (!named_metadata)
+ {
+ if (log)
+ log->PutCString("No global metadata");
+
+ 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)
+ {
+ metadata_node = named_metadata->getOperand(node_index);
+
+ if (metadata_node->getNumOperands() != 2)
+ continue;
+
+ if (metadata_node->getOperand(0) == result_global)
+ break;
+ }
+
+ if (!metadata_node)
+ {
+ if (log)
+ log->PutCString("Couldn't find result metadata");
+ return false;
+ }
+
+ ConstantInt *constant_int = dyn_cast<ConstantInt>(metadata_node->getOperand(1));
+
+ uint64_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 (result_decl->getType().getAsOpaquePtr(),
+ &result_decl->getASTContext());
+ std::string new_result_name;
+
+ m_decl_map->GetPersistentResultName(new_result_name);
+ m_decl_map->AddPersistentVariable(new_result_name.c_str(), result_decl_type);
+
+ if (log)
+ log->Printf("Creating a new result global: %s", new_result_name.c_str());
+
+ // Construct a new result global and set up its metadata
+
+ GlobalVariable *new_result_global = new GlobalVariable(M,
+ result_global->getType()->getElementType(),
+ false, /* not constant */
+ GlobalValue::ExternalLinkage,
+ NULL, /* no initializer */
+ new_result_name.c_str());
+
+ // It's too late in compilation to create a new VarDecl for this, but we don't
+ // need to. We point the metadata at the old VarDecl. This creates an odd
+ // anomaly: a variable with a Value whose name is something like $0 and a
+ // Decl whose name is ___clang_expr_result. This condition is handled in
+ // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is
+ // fixed up.
+
+ ConstantInt *new_constant_int = ConstantInt::get(constant_int->getType(),
+ result_decl_intptr,
+ false);
+
+ llvm::Value* values[2];
+ values[0] = new_result_global;
+ values[1] = new_constant_int;
+
+ MDNode *persistent_global_md = MDNode::get(M.getContext(), values, 2);
+ named_metadata->addOperand(persistent_global_md);
+
+ if (log)
+ log->Printf("Replacing %s with %s",
+ PrintValue(result_global).c_str(),
+ PrintValue(new_result_global).c_str());
+
+ result_global->replaceAllUsesWith(new_result_global);
+ result_global->eraseFromParent();
+
+ return true;
+}
+
static bool isObjCSelectorRef(Value *V)
{
GlobalVariable *GV = dyn_cast<GlobalVariable>(V);
@@ -234,9 +358,12 @@ IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc,
uintptr_t ptr = constant_int->getZExtValue();
- clang::NamedDecl *decl = reinterpret_cast<clang::NamedDecl *>(ptr);
+ clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr);
- if (!m_decl_map->AddPersistentVariable(decl))
+ lldb_private::TypeFromParser result_decl_type (decl->getType().getAsOpaquePtr(),
+ &decl->getASTContext());
+
+ if (!m_decl_map->AddPersistentVariable(decl->getName().str().c_str(), result_decl_type))
return false;
GlobalVariable *persistent_global = new GlobalVariable(M,
@@ -760,7 +887,7 @@ IRForTarget::replaceVariables(Module &M, Function &F)
if (log)
log->Printf(" %s (%s) placed at %d",
- decl->getIdentifier()->getNameStart(),
+ value->getName().str().c_str(),
PrintValue(value, true).c_str(),
offset);
@@ -797,6 +924,13 @@ IRForTarget::runOnModule(Module &M)
Function::iterator bbi;
+ ////////////////////////////////////////////////////////////
+ // Replace __clang_expr_result with a persistent variable
+ //
+
+ if (!createResultVariable(M, *function))
+ return false;
+
//////////////////////////////////
// Run basic-block level passes
//
OpenPOWER on IntegriCloud