Added automatically generated result variables for each
expression.  It is now possible to do things like this:

(lldb) expr int $i = 5; $i + 1
$0 = (int) 6
(lldb) expr $i + 3
$1 = (int) 8
(lldb) expr $1 + $0
$2 = (int) 14

As a bonus, this allowed us to move printing of
expression results into the ClangPersistentVariable
class.  This code needs a bit of refactoring -- in
particular, ClangExpressionDeclMap has eaten one too
many bacteria and needs to undergo mitosis -- but the
infrastructure appears to be holding up nicely.


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@110896 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Expression/IRForTarget.cpp b/source/Expression/IRForTarget.cpp
index 9541945..ca1aeb4 100644
--- a/source/Expression/IRForTarget.cpp
+++ b/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 @@
 {
 }
 
+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 @@
     
     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 @@
         
         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 @@
         
     Function::iterator bbi;
     
+    ////////////////////////////////////////////////////////////
+    // Replace __clang_expr_result with a persistent variable
+    //
+    
+    if (!createResultVariable(M, *function))
+        return false;
+    
     //////////////////////////////////
     // Run basic-block level passes
     //