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/ClangExpression.cpp b/source/Expression/ClangExpression.cpp
index 0e103b6..467acbd 100644
--- a/source/Expression/ClangExpression.cpp
+++ b/source/Expression/ClangExpression.cpp
@@ -239,6 +239,7 @@
     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/source/Expression/ClangExpressionDeclMap.cpp b/source/Expression/ClangExpressionDeclMap.cpp
index b50d68e..da4333c 100644
--- a/source/Expression/ClangExpressionDeclMap.cpp
+++ b/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 @@
 // 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,35 +426,42 @@
         
         if (!GetIndexForDecl(tuple_index, iter->m_decl)) 
         {
-            if (iter->m_name.find("___clang_expr_result") == std::string::npos)
+            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 (log)
+                    log->Printf("Found special result variable %s", iter->m_name.c_str());
+                
+                if (dematerialize)
+                {
+                    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;
+                }
+            }
+            else
             {
                 err.SetErrorStringWithFormat("Unexpected variable %s", iter->m_name.c_str());
                 return false;
             }
             
-            if (log)
-                log->Printf("Found special result variable %s", iter->m_name.c_str());
-            
-            if (dematerialize)
-            {
-                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;
-            }
-            
             continue;
         }
         
@@ -441,6 +474,50 @@
     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 @@
     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 @@
 }
 
 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/source/Expression/ClangPersistentVariables.cpp b/source/Expression/ClangPersistentVariables.cpp
new file mode 100644
index 0000000..dbeac00
--- /dev/null
+++ b/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/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;    
 }