summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
authorSean Callanan <scallanan@apple.com>2010-08-11 03:57:18 +0000
committerSean Callanan <scallanan@apple.com>2010-08-11 03:57:18 +0000
commit2235f32bbdddf52d1e3a1119c747a0861143616d (patch)
treef3977aa629f768c113feee2f5f2ae99d09e67d47 /lldb/source
parent00012c869f519848cb2463c036c27d5a60e8275c (diff)
downloadbcm5719-llvm-2235f32bbdddf52d1e3a1119c747a0861143616d.tar.gz
bcm5719-llvm-2235f32bbdddf52d1e3a1119c747a0861143616d.zip
Added support for persistent variables to the
expression parser. It is now possible to type: (lldb) expr int $i = 5; $i + 1 (int) 6 (lldb) expr $i + 2 (int) 7 The skeleton for automatic result variables is also implemented. The changes affect: - the process, which now contains a ClangPersistentVariables object that holds persistent variables associated with it - the expression parser, which now uses the persistent variables during variable lookup - TaggedASTType, where I loaded some commonly used tags into a header so that they are interchangeable between different clients of the class llvm-svn: 110777
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/Commands/CommandObjectExpression.cpp4
-rw-r--r--lldb/source/Expression/ClangExpression.cpp1
-rw-r--r--lldb/source/Expression/ClangExpressionDeclMap.cpp148
-rw-r--r--lldb/source/Expression/ClangPersistentVariables.cpp59
-rw-r--r--lldb/source/Expression/IRForTarget.cpp151
-rw-r--r--lldb/source/Target/Process.cpp9
6 files changed, 320 insertions, 52 deletions
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index 404dc2a2606..7d83b2c722b 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -19,6 +19,7 @@
#include "lldb/Expression/ClangExpression.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/ClangExpressionVariable.h"
+#include "lldb/Expression/ClangPersistentVariables.h"
#include "lldb/Expression/ClangFunction.h"
#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Host/Host.h"
@@ -217,8 +218,7 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream
return false;
}
- ClangPersistentVariables persistent_vars; /* TODO store this somewhere sensible */
- ClangExpressionDeclMap expr_decl_map (&m_exe_ctx, persistent_vars);
+ ClangExpressionDeclMap expr_decl_map (&m_exe_ctx);
ClangExpression clang_expr (target_triple.AsCString (), &expr_decl_map);
//////////////////////////
diff --git a/lldb/source/Expression/ClangExpression.cpp b/lldb/source/Expression/ClangExpression.cpp
index 0e103b65efb..467acbd3f8d 100644
--- a/lldb/source/Expression/ClangExpression.cpp
+++ b/lldb/source/Expression/ClangExpression.cpp
@@ -239,6 +239,7 @@ ClangExpression::CreateCompilerInstance (bool &IsAST)
m_clang_ap->getLangOpts().ObjC1 = true;
m_clang_ap->getLangOpts().ThreadsafeStatics = false;
m_clang_ap->getLangOpts().AccessControl = false; // Debuggers get universal access
+ m_clang_ap->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name
// Set CodeGen options
m_clang_ap->getCodeGenOpts().EmitDeclMetadata = true;
diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp
index b50d68ef64a..da4333c49c7 100644
--- a/lldb/source/Expression/ClangExpressionDeclMap.cpp
+++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp
@@ -19,6 +19,7 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Expression/ClangASTSource.h"
+#include "lldb/Expression/ClangPersistentVariables.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
@@ -36,17 +37,17 @@
using namespace lldb_private;
using namespace clang;
-ClangExpressionDeclMap::ClangExpressionDeclMap(ExecutionContext *exe_ctx,
- ClangPersistentVariables &persistent_vars) :
- m_exe_ctx(exe_ctx),
- m_persistent_vars(persistent_vars),
- m_struct_laid_out(false),
+ClangExpressionDeclMap::ClangExpressionDeclMap(ExecutionContext *exe_ctx) :
+ m_exe_ctx(exe_ctx), m_struct_laid_out(false),
m_materialized_location(0)
{
if (exe_ctx && exe_ctx->frame)
m_sym_ctx = new SymbolContext(exe_ctx->frame->GetSymbolContext(lldb::eSymbolContextEverything));
else
m_sym_ctx = NULL;
+
+ if (exe_ctx && exe_ctx->process)
+ m_persistent_vars = &exe_ctx->process->GetPersistentVariables();
}
ClangExpressionDeclMap::~ClangExpressionDeclMap()
@@ -83,6 +84,31 @@ ClangExpressionDeclMap::GetIndexForDecl (uint32_t &index,
// Interface for IRForTarget
bool
+ClangExpressionDeclMap::AddPersistentVariable (const clang::NamedDecl *decl)
+{
+ 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()),
+ context);
+
+ ConstString const_name(decl->getName().str().c_str());
+
+ ClangPersistentVariable *pvar = m_persistent_vars->CreateVariable(const_name, user_type);
+
+ if (!pvar)
+ return false;
+
+ return true;
+}
+
+bool
ClangExpressionDeclMap::AddValueToStruct (llvm::Value *value,
const clang::NamedDecl *decl,
std::string &name,
@@ -400,33 +426,40 @@ ClangExpressionDeclMap::DoMaterialize (bool dematerialize,
if (!GetIndexForDecl(tuple_index, iter->m_decl))
{
- if (iter->m_name.find("___clang_expr_result") == std::string::npos)
+ if (iter->m_name[0] == '$')
{
- err.SetErrorStringWithFormat("Unexpected variable %s", iter->m_name.c_str());
- return false;
+ if (!DoMaterializeOnePersistentVariable(dematerialize, *exe_ctx, iter->m_name.c_str(), m_materialized_location + iter->m_offset, err))
+ return false;
}
-
- if (log)
- log->Printf("Found special result variable %s", iter->m_name.c_str());
-
- if (dematerialize)
+ else if (iter->m_name.find("___clang_expr_result") != std::string::npos)
{
- clang::ASTContext *context(exe_ctx->target->GetScratchClangASTContext()->getASTContext());
+ if (log)
+ log->Printf("Found special result variable %s", iter->m_name.c_str());
- if (!context)
+ if (dematerialize)
{
- err.SetErrorString("Couldn't find a scratch AST context to put the result type into");
+ clang::ASTContext *context(exe_ctx->target->GetScratchClangASTContext()->getASTContext());
+
+ if (!context)
+ {
+ err.SetErrorString("Couldn't find a scratch AST context to put the result type into");
+ }
+
+ TypeFromUser copied_type(ClangASTContext::CopyType(context,
+ iter->m_parser_type.GetASTContext(),
+ iter->m_parser_type.GetOpaqueQualType()),
+ context);
+
+ result_value->SetContext(Value::eContextTypeOpaqueClangQualType, copied_type.GetOpaqueQualType());
+
+ result_value->SetValueType(Value::eValueTypeLoadAddress);
+ result_value->GetScalar() = (uintptr_t)m_materialized_location + iter->m_offset;
}
-
- TypeFromUser copied_type(ClangASTContext::CopyType(context,
- iter->m_parser_type.GetASTContext(),
- iter->m_parser_type.GetOpaqueQualType()),
- context);
-
- result_value->SetContext(Value::eContextTypeOpaqueClangQualType, copied_type.GetOpaqueQualType());
-
- result_value->SetValueType(Value::eValueTypeLoadAddress);
- result_value->GetScalar() = (uintptr_t)m_materialized_location + iter->m_offset;
+ }
+ else
+ {
+ err.SetErrorStringWithFormat("Unexpected variable %s", iter->m_name.c_str());
+ return false;
}
continue;
@@ -441,6 +474,50 @@ ClangExpressionDeclMap::DoMaterialize (bool dematerialize,
return true;
}
+bool
+ClangExpressionDeclMap::DoMaterializeOnePersistentVariable(bool dematerialize,
+ ExecutionContext &exe_ctx,
+ const char *name,
+ lldb::addr_t addr,
+ Error &err)
+{
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+
+ if (log)
+ log->Printf("Found persistent variable %s", name);
+
+ ClangPersistentVariable *pvar(m_persistent_vars->GetVariable(ConstString(name)));
+
+ if (!pvar)
+ {
+ err.SetErrorStringWithFormat("Undefined persistent variable %s", name);
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ size_t pvar_size = pvar->Size();
+ uint8_t *pvar_data = pvar->Data();
+ Error error;
+
+ if (dematerialize)
+ {
+ if (exe_ctx.process->ReadMemory (addr, pvar_data, pvar_size, error) != pvar_size)
+ {
+ err.SetErrorStringWithFormat ("Couldn't read a composite type from the target: %s", error.AsCString());
+ return false;
+ }
+ }
+ else
+ {
+ if (exe_ctx.process->WriteMemory (addr, pvar_data, pvar_size, error) != pvar_size)
+ {
+ err.SetErrorStringWithFormat ("Couldn't write a composite type to the target: %s", error.AsCString());
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool
ClangExpressionDeclMap::DoMaterializeOneVariable(bool dematerialize,
ExecutionContext &exe_ctx,
@@ -682,6 +759,11 @@ ClangExpressionDeclMap::GetDecls(NameSearchContext &context,
if (var)
AddOneVariable(context, var);
+ ClangPersistentVariable *pvar(m_persistent_vars->GetVariable(ConstString(name)));
+
+ if (pvar)
+ AddOneVariable(context, pvar);
+
/* Commented out pending resolution of a loop when the TagType is imported
lldb::TypeSP type = m_sym_ctx->FindTypeByName(name_cs);
@@ -824,6 +906,20 @@ ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
}
void
+ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
+ ClangPersistentVariable *pvar)
+{
+ TypeFromUser user_type = pvar->Type();
+
+ TypeFromParser parser_type(ClangASTContext::CopyType(context.GetASTContext(),
+ user_type.GetASTContext(),
+ user_type.GetOpaqueQualType()),
+ context.GetASTContext());
+
+ (void)context.AddVarDecl(parser_type.GetOpaqueQualType());
+}
+
+void
ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
Function* fun,
Symbol* symbol)
diff --git a/lldb/source/Expression/ClangPersistentVariables.cpp b/lldb/source/Expression/ClangPersistentVariables.cpp
new file mode 100644
index 00000000000..dbeac006250
--- /dev/null
+++ b/lldb/source/Expression/ClangPersistentVariables.cpp
@@ -0,0 +1,59 @@
+//===-- ClangPersistentVariables.cpp ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangPersistentVariables.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+
+using namespace lldb_private;
+using namespace clang;
+
+ClangPersistentVariables::ClangPersistentVariables () :
+ m_variables(),
+ m_result_counter(0)
+{
+}
+
+ClangPersistentVariable *
+ClangPersistentVariables::CreateVariable (ConstString name,
+ TypeFromUser user_type)
+{
+ ClangPersistentVariable new_var(user_type);
+
+ if (m_variables.find(name) != m_variables.end())
+ return NULL;
+
+ m_variables[name] = new_var;
+
+ return &m_variables[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())
+ return NULL;
+
+ return &m_variables[name];
+}
diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Expression/IRForTarget.cpp
index 4f3a740e0bb..9541945eebc 100644
--- a/lldb/source/Expression/IRForTarget.cpp
+++ b/lldb/source/Expression/IRForTarget.cpp
@@ -37,6 +37,20 @@ IRForTarget::IRForTarget(const void *pid,
{
}
+/* A handy utility function used at several places in the code */
+
+static std::string
+PrintValue(Value *V, bool truncate = false)
+{
+ std::string s;
+ raw_string_ostream rso(s);
+ V->print(rso);
+ rso.flush();
+ if (truncate)
+ s.resize(s.length() - 1);
+ return s;
+}
+
IRForTarget::~IRForTarget()
{
}
@@ -200,6 +214,97 @@ IRForTarget::rewriteObjCSelectors(Module &M,
return true;
}
+bool
+IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc,
+ llvm::Module &M)
+{
+ AllocaInst *alloc = dyn_cast<AllocaInst>(persistent_alloc);
+
+ MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr");
+
+ if (!alloc_md || !alloc_md->getNumOperands())
+ return false;
+
+ ConstantInt *constant_int = dyn_cast<ConstantInt>(alloc_md->getOperand(0));
+
+ if (!constant_int)
+ return false;
+
+ // We attempt to register this as a new persistent variable with the DeclMap.
+
+ uintptr_t ptr = constant_int->getZExtValue();
+
+ clang::NamedDecl *decl = reinterpret_cast<clang::NamedDecl *>(ptr);
+
+ if (!m_decl_map->AddPersistentVariable(decl))
+ return false;
+
+ GlobalVariable *persistent_global = new GlobalVariable(M,
+ alloc->getType()->getElementType(),
+ false, /* not constant */
+ GlobalValue::ExternalLinkage,
+ NULL, /* no initializer */
+ alloc->getName().str().c_str());
+
+ // What we're going to do here is make believe this was a regular old external
+ // variable. That means we need to make the metadata valid.
+
+ NamedMDNode *named_metadata = M.getNamedMetadata("clang.global.decl.ptrs");
+
+ llvm::Value* values[2];
+ values[0] = persistent_global;
+ values[1] = constant_int;
+
+ MDNode *persistent_global_md = MDNode::get(M.getContext(), values, 2);
+ named_metadata->addOperand(persistent_global_md);
+
+ alloc->replaceAllUsesWith(persistent_global);
+ alloc->eraseFromParent();
+
+ return true;
+}
+
+bool
+IRForTarget::rewritePersistentAllocs(llvm::Module &M,
+ llvm::BasicBlock &BB)
+{
+ lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+
+ BasicBlock::iterator ii;
+
+ typedef SmallVector <Instruction*, 2> InstrList;
+ typedef InstrList::iterator InstrIterator;
+
+ InstrList pvar_allocs;
+
+ for (ii = BB.begin();
+ ii != BB.end();
+ ++ii)
+ {
+ Instruction &inst = *ii;
+
+ if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst))
+ if (alloc->getName().startswith("$"))
+ pvar_allocs.push_back(alloc);
+ }
+
+ InstrIterator iter;
+
+ for (iter = pvar_allocs.begin();
+ iter != pvar_allocs.end();
+ ++iter)
+ {
+ if (!RewritePersistentAlloc(*iter, M))
+ {
+ if(log)
+ log->PutCString("Couldn't rewrite the creation of a persistent variable");
+ return false;
+ }
+ }
+
+ return true;
+}
+
static clang::NamedDecl *
DeclForGlobalValue(Module &module,
GlobalValue *global_value)
@@ -222,7 +327,7 @@ DeclForGlobalValue(Module &module,
return NULL;
if (metadata_node->getNumOperands() != 2)
- return NULL;
+ continue;
if (metadata_node->getOperand(0) != global_value)
continue;
@@ -400,18 +505,6 @@ IRForTarget::resolveExternals(Module &M, BasicBlock &BB)
return true;
}
-static std::string
-PrintValue(Value *V, bool truncate = false)
-{
- std::string s;
- raw_string_ostream rso(s);
- V->print(rso);
- rso.flush();
- if (truncate)
- s.resize(s.length() - 1);
- return s;
-}
-
static bool isGuardVariableRef(Value *V)
{
ConstantExpr *C = dyn_cast<ConstantExpr>(V);
@@ -518,12 +611,21 @@ UnfoldConstant(Constant *C, Value *new_value, Instruction *first_entry_instructi
Value::use_iterator ui;
+ SmallVector<User*, 16> users;
+
+ // We do this because the use list might change, invalidating our iterator.
+ // Much better to keep a work list ourselves.
for (ui = C->use_begin();
ui != C->use_end();
++ui)
- {
- User *user = *ui;
+ users.push_back(*ui);
+ for (int i = 0;
+ i < users.size();
+ ++i)
+ {
+ User *user = users[i];
+
if (Constant *constant = dyn_cast<Constant>(user))
{
// synthesize a new non-constant equivalent of the constant
@@ -703,9 +805,12 @@ IRForTarget::runOnModule(Module &M)
bbi != function->end();
++bbi)
{
- if (!rewriteObjCSelectors(M, *bbi))
+ if (!rewritePersistentAllocs(M, *bbi))
return false;
+ if (!rewriteObjCSelectors(M, *bbi))
+ return false;
+
if (!resolveExternals(M, *bbi))
return false;
@@ -713,13 +818,6 @@ IRForTarget::runOnModule(Module &M)
return false;
}
- ///////////////////////////////
- // Run function-level passes
- //
-
- if (!replaceVariables(M, *function))
- return false;
-
if (log)
{
std::string s;
@@ -732,6 +830,13 @@ IRForTarget::runOnModule(Module &M)
log->Printf("Module after preparing for execution: \n%s", s.c_str());
}
+ ///////////////////////////////
+ // Run function-level passes
+ //
+
+ if (!replaceVariables(M, *function))
+ return false;
+
return true;
}
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 1a1f93c2ada..3171c94652f 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -80,7 +80,8 @@ Process::Process(Target &target, Listener &listener) :
m_notifications (),
m_listener(listener),
m_unix_signals (),
- m_objc_object_printer(*this)
+ m_objc_object_printer(*this),
+ m_persistent_vars()
{
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT);
if (log)
@@ -1882,6 +1883,12 @@ Process::GetSP ()
return GetTarget().GetProcessSP();
}
+ClangPersistentVariables &
+Process::GetPersistentVariables()
+{
+ return m_persistent_vars;
+}
+
ObjCObjectPrinter &
Process::GetObjCObjectPrinter()
{
OpenPOWER on IntegriCloud