[Lldb-commits] [lldb] r110896 - in /lldb/trunk: include/lldb/Expression/ClangExpressionDeclMap.h include/lldb/Expression/ClangPersistentVariables.h include/lldb/Expression/IRForTarget.h source/Commands/CommandObjectExpression.cpp source/Expression/ClangExpressionDeclMap.cpp source/Expression/ClangPersistentVariables.cpp source/Expression/IRForTarget.cpp

Sean Callanan scallanan at apple.com
Wed Aug 11 18:56:52 PDT 2010


Author: spyffe
Date: Wed Aug 11 20:56:52 2010
New Revision: 110896

URL: http://llvm.org/viewvc/llvm-project?rev=110896&view=rev
Log:
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.

Modified:
    lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h
    lldb/trunk/include/lldb/Expression/ClangPersistentVariables.h
    lldb/trunk/include/lldb/Expression/IRForTarget.h
    lldb/trunk/source/Commands/CommandObjectExpression.cpp
    lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
    lldb/trunk/source/Expression/ClangPersistentVariables.cpp
    lldb/trunk/source/Expression/IRForTarget.cpp

Modified: lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h?rev=110896&r1=110895&r2=110896&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h Wed Aug 11 20:56:52 2010
@@ -48,7 +48,8 @@
                           const clang::Decl *decl);
     
     // Interface for IRForTarget
-    bool AddPersistentVariable (const clang::NamedDecl *decl);
+    void GetPersistentResultName (std::string &name);
+    bool AddPersistentVariable (const char *name, TypeFromParser type);
     bool AddValueToStruct (llvm::Value *value,
                            const clang::NamedDecl *decl,
                            std::string &name,
@@ -84,7 +85,7 @@
                                 Error &error);
     
     bool Dematerialize(ExecutionContext *exe_ctx,
-                       lldb_private::Value &result_value,
+                       ClangPersistentVariable *&result,
                        Error &error);
     
     // Interface for ClangASTSource
@@ -127,6 +128,7 @@
     bool                        m_struct_laid_out;
     lldb::addr_t                m_allocated_area;
     lldb::addr_t                m_materialized_location;
+    std::string                 m_result_name;
         
     Variable *FindVariableInScope(const SymbolContext &sym_ctx,
                                   const char *name,
@@ -145,7 +147,7 @@
     
     bool DoMaterialize (bool dematerialize,
                         ExecutionContext *exe_ctx,
-                        lldb_private::Value *result_value, /* must be non-NULL if D is set */
+                        ClangPersistentVariable **result, /* must be non-NULL if D is set */
                         Error &err);
 
     bool DoMaterializeOnePersistentVariable(bool dematerialize,

Modified: lldb/trunk/include/lldb/Expression/ClangPersistentVariables.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangPersistentVariables.h?rev=110896&r1=110895&r2=110896&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangPersistentVariables.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangPersistentVariables.h Wed Aug 11 20:56:52 2010
@@ -26,12 +26,14 @@
     friend class ClangPersistentVariables;
 public:
     ClangPersistentVariable () :
+        m_name(),
         m_user_type(),
         m_data()
     {
     }
     
     ClangPersistentVariable (const ClangPersistentVariable &pv) :
+        m_name(pv.m_name),
         m_user_type(pv.m_user_type),
         m_data(pv.m_data)
     {
@@ -39,6 +41,7 @@
     
     ClangPersistentVariable &operator=(const ClangPersistentVariable &pv)
     {
+        m_name = pv.m_name;
         m_user_type = pv.m_user_type;
         m_data = pv.m_data;
         return *this;
@@ -58,12 +61,21 @@
     {
         return m_user_type;
     }
+    
+    Error Print(Stream &output_stream,
+                ExecutionContext &exe_ctx,
+                lldb::Format format,
+                bool show_types,
+                bool show_summary,
+                bool verbose);
 private:
-    ClangPersistentVariable (TypeFromUser user_type)
+    ClangPersistentVariable (ConstString name, TypeFromUser user_type)
     {
+        m_name = name;
         m_user_type = user_type;
         m_data = lldb::DataBufferSP(new DataBufferHeap(Size(), 0));
     }
+    ConstString         m_name;
     TypeFromUser        m_user_type;
     lldb::DataBufferSP  m_data;
 };
@@ -72,9 +84,10 @@
 {
 public:
     ClangPersistentVariable *CreateVariable (ConstString name, TypeFromUser user_type);
-    ClangPersistentVariable *CreateResultVariable (TypeFromUser user_type);
     ClangPersistentVariable *GetVariable (ConstString name);
     
+    void GetNextResultName(std::string &name);
+    
     ClangPersistentVariables ();
 private:
     typedef std::map <ConstString, ClangPersistentVariable>    PVarMap;

Modified: lldb/trunk/include/lldb/Expression/IRForTarget.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/IRForTarget.h?rev=110896&r1=110895&r2=110896&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/IRForTarget.h (original)
+++ lldb/trunk/include/lldb/Expression/IRForTarget.h Wed Aug 11 20:56:52 2010
@@ -39,6 +39,12 @@
                            llvm::PassManagerType T = llvm::PMT_ModulePassManager);
     llvm::PassManagerType getPotentialPassManagerType() const;
 private:
+    // pass to find the result variable created in the result synthesizer and
+    // make a result variable out of it (or a void variable if there is no
+    // result)
+    bool createResultVariable(llvm::Module &M,
+                              llvm::Function &F);
+    
     // pass to rewrite Objective-C method calls to use the runtime function
     // sel_registerName
     bool RewriteObjCSelector(llvm::Instruction* selector_load,

Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=110896&r1=110895&r2=110896&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Wed Aug 11 20:56:52 2010
@@ -252,7 +252,7 @@
     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 @@
                     
         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)
+    if (expr_result)
     {
-        // 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 (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;
 }
 

Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=110896&r1=110895&r2=110896&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Wed Aug 11 20:56:52 2010
@@ -83,22 +83,25 @@
 
 // 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 @@
 
 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 @@
 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 @@
         
         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
             {

Modified: lldb/trunk/source/Expression/ClangPersistentVariables.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangPersistentVariables.cpp?rev=110896&r1=110895&r2=110896&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangPersistentVariables.cpp (original)
+++ lldb/trunk/source/Expression/ClangPersistentVariables.cpp Wed Aug 11 20:56:52 2010
@@ -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 @@
 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 @@
 }
 
 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 @@
     
     return &m_variables[name];
 }
+
+void
+ClangPersistentVariables::GetNextResultName (std::string &name)
+{
+    StreamString s;
+    s.Printf("$%llu", m_result_counter);
+    
+    m_result_counter++;
+    
+    name = s.GetString();
+}

Modified: lldb/trunk/source/Expression/IRForTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRForTarget.cpp?rev=110896&r1=110895&r2=110896&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRForTarget.cpp (original)
+++ lldb/trunk/source/Expression/IRForTarget.cpp Wed Aug 11 20:56:52 2010
@@ -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);
+    
+    lldb_private::TypeFromParser result_decl_type (decl->getType().getAsOpaquePtr(),
+                                                   &decl->getASTContext());
     
-    if (!m_decl_map->AddPersistentVariable(decl))
+    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
     //





More information about the lldb-commits mailing list