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
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@110777 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Expression/IRForTarget.cpp b/source/Expression/IRForTarget.cpp
index 4f3a740..9541945 100644
--- a/source/Expression/IRForTarget.cpp
+++ b/source/Expression/IRForTarget.cpp
@@ -37,6 +37,20 @@
{
}
+/* 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 @@
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 @@
return NULL;
if (metadata_node->getNumOperands() != 2)
- return NULL;
+ continue;
if (metadata_node->getOperand(0) != global_value)
continue;
@@ -400,18 +505,6 @@
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 @@
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 @@
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 @@
return false;
}
- ///////////////////////////////
- // Run function-level passes
- //
-
- if (!replaceVariables(M, *function))
- return false;
-
if (log)
{
std::string s;
@@ -732,6 +830,13 @@
log->Printf("Module after preparing for execution: \n%s", s.c_str());
}
+ ///////////////////////////////
+ // Run function-level passes
+ //
+
+ if (!replaceVariables(M, *function))
+ return false;
+
return true;
}