[Lldb-commits] [lldb] r123371 - in /lldb/trunk: include/lldb/Expression/ include/lldb/Symbol/ include/lldb/Target/ source/API/ source/Breakpoint/ source/Commands/ source/Core/ source/Expression/ source/Plugins/Process/gdb-remote/ source/Symbol/ source/Target/

Sean Callanan scallanan at apple.com
Thu Jan 13 00:53:35 PST 2011


Author: spyffe
Date: Thu Jan 13 02:53:35 2011
New Revision: 123371

URL: http://llvm.org/viewvc/llvm-project?rev=123371&view=rev
Log:
Implemented a major overhaul of the way variables are handled
by LLDB.  Instead of being materialized into the input structure
passed to the expression, variables are left in place and pointers
to them are materialzied into the structure.  Variables not resident
in memory (notably, registers) get temporary memory regions allocated
for them.

Persistent variables are the most complex part of this, because they
are made in various ways and there are different expectations about
their lifetime.  Persistent variables now have flags indicating their
status and what the expectations for longevity are.  They can be
marked as residing in target memory permanently -- this is the
default for result variables from expressions entered on the command
line and for explicitly declared persistent variables (but more on
that below).  Other result variables have their memory freed.

Some major improvements resulting from this include being able to
properly take the address of variables, better and cleaner support
for functions that return references, and cleaner C++ support in
general.  One problem that remains is the problem of explicitly
declared persistent variables; I have not yet implemented the code
that makes references to them into indirect references, so currently
materialization and dematerialization of these variables is broken.

Modified:
    lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h
    lldb/trunk/include/lldb/Expression/ClangExpressionVariable.h
    lldb/trunk/include/lldb/Expression/ClangUserExpression.h
    lldb/trunk/include/lldb/Expression/IRForTarget.h
    lldb/trunk/include/lldb/Symbol/ClangASTContext.h
    lldb/trunk/include/lldb/Target/Target.h
    lldb/trunk/source/API/SBFrame.cpp
    lldb/trunk/source/Breakpoint/BreakpointOptions.cpp
    lldb/trunk/source/Commands/CommandObjectExpression.cpp
    lldb/trunk/source/Core/ValueObject.cpp
    lldb/trunk/source/Expression/ASTResultSynthesizer.cpp
    lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
    lldb/trunk/source/Expression/ClangExpressionVariable.cpp
    lldb/trunk/source/Expression/ClangUserExpression.cpp
    lldb/trunk/source/Expression/ClangUtilityFunction.cpp
    lldb/trunk/source/Expression/IRForTarget.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
    lldb/trunk/source/Symbol/ClangASTContext.cpp
    lldb/trunk/source/Target/Process.cpp
    lldb/trunk/source/Target/Target.cpp

Modified: lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h Thu Jan 13 02:53:35 2011
@@ -70,9 +70,14 @@
     //------------------------------------------------------------------
     /// Constructor
     ///
-    /// Initializes class variabes.
+    /// Initializes class variables.
+    ///
+    /// @param[in] keep_result_in_memory
+    ///     If true, inhibits the normal deallocation of the memory for
+    ///     the result persistent variable, and instead marks the variable
+    ///     as persisting.
     //------------------------------------------------------------------
-    ClangExpressionDeclMap ();
+    ClangExpressionDeclMap (bool keep_result_in_memory);
     
     //------------------------------------------------------------------
     /// Destructor
@@ -151,7 +156,9 @@
     bool 
     AddPersistentVariable (const clang::NamedDecl *decl,
                            const ConstString &name, 
-                           TypeFromParser type);
+                           TypeFromParser type,
+                           bool is_result,
+                           bool is_lvalue);
     
     //------------------------------------------------------------------
     /// [Used by IRForTarget] Add a variable to the struct that needs to
@@ -443,6 +450,7 @@
 private:
     ClangExpressionVariableList    m_found_entities;           ///< All entities that were looked up for the parser.
     ClangExpressionVariableList    m_struct_members;           ///< All entities that need to be placed in the struct.
+    bool                           m_keep_result_in_memory;    ///< True if result persistent variables generated by this expression should stay in memory.
     
     //----------------------------------------------------------------------
     /// The following values should not live beyond parsing
@@ -797,11 +805,11 @@
     /// @param[in] sym_ctx
     ///     The symbol context to use (for looking the variable up).
     ///
-    /// @param[in] name
-    ///     The name of the variable (for looking the variable up).
-    ///
-    /// @param[in] type
-    ///     The required type of the variable (for looking the variable up).
+    /// @param[in] expr_var
+    ///     The entity that the expression parser uses for the variable.
+    ///     In case the variable needs to be copied into the target's
+    ///     memory, this location is stored in the variable during
+    ///     materialization and cleared when it is demateralized.
     ///
     /// @param[in] addr
     ///     The address at which to materialize the variable.
@@ -817,8 +825,7 @@
     DoMaterializeOneVariable (bool dematerialize,
                               ExecutionContext &exe_ctx,
                               const SymbolContext &sym_ctx,
-                              const ConstString &name,
-                              TypeFromUser type,
+                              lldb::ClangExpressionVariableSP &expr_var,
                               lldb::addr_t addr, 
                               Error &err);
     

Modified: lldb/trunk/include/lldb/Expression/ClangExpressionVariable.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangExpressionVariable.h?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangExpressionVariable.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangExpressionVariable.h Thu Jan 13 02:53:35 2011
@@ -199,7 +199,6 @@
     void
     ValueUpdated ();
 
-
     typedef lldb::SharedPtr<ValueObjectConstResult>::Type ValueObjectConstResultSP;
 
     //----------------------------------------------------------------------
@@ -207,9 +206,22 @@
     //----------------------------------------------------------------------
     std::auto_ptr<ParserVars> m_parser_vars;
     std::auto_ptr<JITVars> m_jit_vars;
-    //ValueObjectConstResultSP m_valojb_sp;
-    lldb::ValueObjectSP m_valojb_sp;
-
+    
+    enum Flags 
+    {
+        EVNone                  = 0,
+        EVIsLLDBAllocated       = 1 << 0,   ///< This variable is resident in a location specifically allocated for it by LLDB in the target process
+        EVIsProgramReference    = 1 << 1,   ///< This variable is a reference to a (possibly invalid) area managed by the target program
+        EVNeedsAllocation       = 1 << 2,   ///< Space for this variable has yet to be allocated in the target process
+        EVIsFreezeDried         = 1 << 3,   ///< This variable's authoritative version is in m_frozen_sp (for example, for statically-computed results)
+        EVNeedsFreezeDry        = 1 << 4,   ///< Copy from m_live_sp to m_frozen_sp during dematerialization
+        EVKeepInTarget          = 1 << 5    ///< Keep the allocation after the expression is complete rather than freeze drying its contents and freeing it
+    };
+    
+    uint16_t m_flags; // takes elements of Flags
+    
+    lldb::ValueObjectSP m_frozen_sp;
+    lldb::ValueObjectSP m_live_sp;
 private:
     DISALLOW_COPY_AND_ASSIGN (ClangExpressionVariable);
 };

Modified: lldb/trunk/include/lldb/Expression/ClangUserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangUserExpression.h?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangUserExpression.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangUserExpression.h Thu Jan 13 02:53:35 2011
@@ -81,6 +81,10 @@
     ///     The type that the expression should be coerced to.  If NULL,
     ///     inferred from the expression itself.
     ///
+    /// @param[in] keep_result_in_memory
+    ///     True if the resulting persistent variable should reside in 
+    ///     target memory, if applicable.
+    ///
     /// @param[out] const_result
     ///     If this is non-NULL, the expression has no side effects, and 
     ///     the expression returns a constant result, then that result 
@@ -93,6 +97,7 @@
     Parse (Stream &error_stream, 
            ExecutionContext &exe_ctx,
            TypeFromUser desired_type,
+           bool keep_result_in_memory,
            lldb::ClangExpressionVariableSP *const_result = NULL);
     
     //------------------------------------------------------------------
@@ -109,6 +114,7 @@
     ///     If true, and the execution stops before completion, we unwind the
     ///     function call, and return the program state to what it was before the
     ///     execution.  If false, we leave the program in the stopped state.
+    ///
     /// @param[in] shared_ptr_to_me
     ///     This is a shared pointer to this ClangUserExpression.  This is
     ///     needed because Execute can push a thread plan that will hold onto
@@ -127,12 +133,14 @@
     Execute (Stream &error_stream,
              ExecutionContext &exe_ctx,
              bool discard_on_error,
+             bool keep_in_memory,
              ClangUserExpressionSP &shared_ptr_to_me,
              lldb::ClangExpressionVariableSP &result);
              
     ThreadPlan *
     GetThreadPlanToExecuteJITExpression (Stream &error_stream,
                                          ExecutionContext &exe_ctx);
+    
     bool
     FinalizeJITExecution (Stream &error_stream,
                           ExecutionContext &exe_ctx,
@@ -232,6 +240,14 @@
     /// @param[in] exe_ctx
     ///     The execution context to use when evaluating the expression.
     ///
+    /// @param[in] discard_on_error
+    ///     True if the thread's state should be restored in the case 
+    ///     of an error.
+    ///
+    /// @param[in] keep_in_memory
+    ///     True if the resulting persistent variable should reside in 
+    ///     target memory, if applicable.
+    ///
     /// @param[in] expr_cstr
     ///     A C string containing the expression to be evaluated.
     ///
@@ -248,6 +264,7 @@
     static lldb::ExecutionResults
     Evaluate (ExecutionContext &exe_ctx, 
               bool discard_on_error,
+              bool keep_in_memory,
               const char *expr_cstr,
               const char *expr_prefix,
               lldb::ValueObjectSP &result_valobj_sp);

Modified: lldb/trunk/include/lldb/Expression/IRForTarget.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/IRForTarget.h?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/IRForTarget.h (original)
+++ lldb/trunk/include/lldb/Expression/IRForTarget.h Thu Jan 13 02:53:35 2011
@@ -448,12 +448,14 @@
     /// Flags
     bool                                    m_resolve_vars;             ///< True if external variable references and persistent variable references should be resolved
     std::string                             m_func_name;                ///< The name of the function to translate
+    lldb_private::ConstString               m_result_name;              ///< The name of the result variable ($0, $1, ...)
     lldb_private::ClangExpressionDeclMap   *m_decl_map;                 ///< The DeclMap containing the Decls 
     llvm::Constant                         *m_CFStringCreateWithBytes;  ///< The address of the function CFStringCreateWithBytes, cast to the appropriate function pointer type
     llvm::Constant                         *m_sel_registerName;         ///< The address of the function sel_registerName, cast to the appropriate function pointer type
     lldb::ClangExpressionVariableSP        *m_const_result;             ///< If non-NULL, this value should be set to the return value of the expression if it is constant and the expression has no side effects
     
     bool                                    m_has_side_effects;         ///< True if the function's result cannot be simply determined statically
+    bool                                    m_result_is_pointer;        ///< True if the function's result in the AST is a pointer (see comments in ASTResultSynthesizer::SynthesizeBodyResult)
     
 private:
     //------------------------------------------------------------------

Modified: lldb/trunk/include/lldb/Symbol/ClangASTContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ClangASTContext.h?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/ClangASTContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/ClangASTContext.h Thu Jan 13 02:53:35 2011
@@ -529,11 +529,25 @@
     CreatePointerType (clang::ASTContext *ast, 
                        lldb::clang_type_t clang_type);
 
+    static lldb::clang_type_t
+    CreateLValueReferenceType (clang::ASTContext *ast_context,
+                               lldb::clang_type_t clang_type);
+    
+    static lldb::clang_type_t
+    CreateRValueReferenceType (clang::ASTContext *ast_context,
+                               lldb::clang_type_t clang_type);
+    
     lldb::clang_type_t
-    CreateLValueReferenceType (lldb::clang_type_t clang_type);
+    CreateLValueReferenceType (lldb::clang_type_t clang_type)
+    {
+        return ClangASTContext::CreateLValueReferenceType(getASTContext(), clang_type);
+    }
 
     lldb::clang_type_t
-    CreateRValueReferenceType (lldb::clang_type_t clang_type);
+    CreateRValueReferenceType (lldb::clang_type_t clang_type)
+    {
+        return ClangASTContext::CreateRValueReferenceType(getASTContext(), clang_type);
+    }
 
     lldb::clang_type_t
     CreateMemberPointerType (lldb::clang_type_t  clang_pointee_type,

Modified: lldb/trunk/include/lldb/Target/Target.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Target.h?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Target.h (original)
+++ lldb/trunk/include/lldb/Target/Target.h Thu Jan 13 02:53:35 2011
@@ -476,6 +476,7 @@
     EvaluateExpression (const char *expression,
                         StackFrame *frame,
                         bool unwind_on_error,
+                        bool keep_in_memory,
                         lldb::ValueObjectSP &result_valobj_sp);
 
     ClangPersistentVariables &

Modified: lldb/trunk/source/API/SBFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBFrame.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/API/SBFrame.cpp (original)
+++ lldb/trunk/source/API/SBFrame.cpp Thu Jan 13 02:53:35 2011
@@ -689,8 +689,9 @@
     {
         ExecutionResults exe_results;
         const bool unwind_on_error = true;
+        const bool keep_in_memory = false;
 
-        exe_results = m_opaque_sp->GetThread().GetProcess().GetTarget().EvaluateExpression(expr, m_opaque_sp.get(), unwind_on_error, *expr_result);
+        exe_results = m_opaque_sp->GetThread().GetProcess().GetTarget().EvaluateExpression(expr, m_opaque_sp.get(), unwind_on_error, keep_in_memory, *expr_result);
     }
     
     if (expr_log)

Modified: lldb/trunk/source/Breakpoint/BreakpointOptions.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointOptions.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointOptions.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointOptions.cpp Thu Jan 13 02:53:35 2011
@@ -199,7 +199,7 @@
     ClangASTContext *ast_context = exe_ctx.target->GetScratchClangASTContext();
     TypeFromUser bool_type(ast_context->GetBuiltInType_bool(), ast_context->getASTContext());
 
-    if (!m_condition_ap->Parse (error_stream, exe_ctx, bool_type))
+    if (!m_condition_ap->Parse (error_stream, exe_ctx, bool_type, false /* keep_in_memory */))
     {
         // Errors mean we should stop.
         return NULL;

Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Thu Jan 13 02:53:35 2011
@@ -237,7 +237,10 @@
         lldb::ValueObjectSP result_valobj_sp;
 
         lldb::ExecutionResults exe_results;
-        exe_results = m_exe_ctx.target->EvaluateExpression(expr, m_exe_ctx.frame, m_options.unwind_on_error, result_valobj_sp);
+        
+        bool keep_in_memory = true;
+        
+        exe_results = m_exe_ctx.target->EvaluateExpression(expr, m_exe_ctx.frame, m_options.unwind_on_error, keep_in_memory, result_valobj_sp);
         
         if (exe_results == eExecutionInterrupted && !m_options.unwind_on_error)
         {

Modified: lldb/trunk/source/Core/ValueObject.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Core/ValueObject.cpp (original)
+++ lldb/trunk/source/Core/ValueObject.cpp Thu Jan 13 02:53:35 2011
@@ -1316,7 +1316,7 @@
                                                                  ClangASTContext::CreatePointerType (ast, clang_type),
                                                                  ConstString (name.c_str()),
                                                                  addr, 
-                                                                 address_type,
+                                                                 eAddressTypeInvalid,
                                                                  m_data.GetAddressByteSize()));
                 }
             }

Modified: lldb/trunk/source/Expression/ASTResultSynthesizer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ASTResultSynthesizer.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ASTResultSynthesizer.cpp (original)
+++ lldb/trunk/source/Expression/ASTResultSynthesizer.cpp Thu Jan 13 02:53:35 2011
@@ -246,6 +246,49 @@
         // No auxiliary variable necessary; expression returns void
         return true;
     
+    // is_lvalue is used to record whether the expression returns an assignable Lvalue or an
+    // Rvalue.  This is relevant because they are handled differently.
+    //
+    // For Lvalues
+    //
+    //   - In AST result synthesis (here!) the expression E is transformed into an initialization
+    //     T *$__lldb_expr_result_ptr = &E.
+    //
+    //   - In structure allocation, a pointer-sized slot is allocated in the struct that is to be
+    //     passed into the expression.
+    //
+    //   - In IR transformations, reads and writes to $__lldb_expr_result_ptr are redirected at
+    //     an entry in the struct ($__lldb_arg) passed into the expression.  (Other persistent
+    //     variables are treated similarly, having been materialized as references, but in those
+    //     cases the value of the reference itself is never modified.)
+    //
+    //   - During materialization, $0 (the result persistent variable) is ignored.
+    //
+    //   - During dematerialization, $0 is marked up as a load address with value equal to the
+    //     contents of the structure entry.
+    //
+    // For Rvalues
+    //
+    //   - In AST result synthesis the expression E is transformed into an initialization
+    //     static T $__lldb_expr_result = E.
+    //
+    //   - In structure allocation, a pointer-sized slot is allocated in the struct that is to be
+    //     passed into the expression.
+    //
+    //   - In IR transformations, an instruction is inserted at the beginning of the function to
+    //     dereference the pointer resident in the slot.  Reads and writes to $__lldb_expr_result
+    //     are redirected at that dereferenced version.  Guard variables for the static variable 
+    //     are excised.
+    //
+    //   - During materialization, $0 (the result persistent variable) is populated with the location
+    //     of a newly-allocated area of memory.
+    //
+    //   - During dematerialization, $0 is ignored.
+
+    bool is_lvalue = 
+        (last_expr->getValueKind() == VK_LValue || last_expr->getValueKind() == VK_XValue) &&
+        (last_expr->getObjectKind() == OK_Ordinary);
+    
     QualType expr_qual_type = last_expr->getType();
     clang::Type *expr_type = expr_qual_type.getTypePtr();
     
@@ -259,22 +302,51 @@
     {
         std::string s = expr_qual_type.getAsString();
         
-        log->Printf("Last statement's type: %s", s.c_str());
+        log->Printf("Last statement is an %s with type: %s", (is_lvalue ? "lvalue" : "rvalue"), s.c_str());
     }
     
-    IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result");
-        
-    clang::VarDecl *result_decl = VarDecl::Create(Ctx, 
-                                                  DC, 
-                                                  SourceLocation(), 
-                                                  &result_id, 
-                                                  expr_qual_type, 
-                                                  NULL, 
-                                                  SC_Static, 
-                                                  SC_Static);
+    clang::VarDecl *result_decl;
     
-    if (!result_decl)
-        return false;
+    if (is_lvalue)
+    {
+        IdentifierInfo &result_ptr_id = Ctx.Idents.get("$__lldb_expr_result_ptr");
+        
+        QualType ptr_qual_type = Ctx.getPointerType(expr_qual_type);
+        
+        result_decl = VarDecl::Create(Ctx,
+                                      DC,
+                                      SourceLocation(),
+                                      &result_ptr_id,
+                                      ptr_qual_type,
+                                      NULL,
+                                      SC_Static,
+                                      SC_Static);
+        
+        if (!result_decl)
+            return false;
+                
+        ExprResult address_of_expr = m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr);
+        
+        m_sema->AddInitializerToDecl(result_decl, address_of_expr.take());
+    }
+    else
+    {
+        IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result");
+        
+        result_decl = VarDecl::Create(Ctx, 
+                                      DC, 
+                                      SourceLocation(), 
+                                      &result_id, 
+                                      expr_qual_type, 
+                                      NULL, 
+                                      SC_Static, 
+                                      SC_Static);
+        
+        if (!result_decl)
+            return false;
+        
+        m_sema->AddInitializerToDecl(result_decl, last_expr);
+    }
     
     DC->addDecl(result_decl);
     
@@ -282,7 +354,7 @@
     // call AddInitializerToDecl
     //
         
-    m_sema->AddInitializerToDecl(result_decl, last_expr);
+    //m_sema->AddInitializerToDecl(result_decl, last_expr);
     
     /////////////////////////////////
     // call ConvertDeclToDeclGroup

Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Thu Jan 13 02:53:35 2011
@@ -45,11 +45,12 @@
 using namespace lldb_private;
 using namespace clang;
 
-ClangExpressionDeclMap::ClangExpressionDeclMap () :
+ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory) :
     m_found_entities (),
     m_struct_members (),
     m_parser_vars (),
-    m_struct_vars ()
+    m_struct_vars (),
+    m_keep_result_in_memory (keep_result_in_memory)
 {
     EnableStructVars();
 }
@@ -187,6 +188,8 @@
                 return lldb::ClangExpressionVariableSP();    
         }
     }
+    
+    pvar_sp->m_flags |= ClangExpressionVariable::EVIsFreezeDried;
 
     return pvar_sp;
 }
@@ -196,11 +199,15 @@
 (
     const clang::NamedDecl *decl, 
     const ConstString &name, 
-    TypeFromParser parser_type
+    TypeFromParser parser_type,
+    bool is_result,
+    bool is_lvalue
 )
 {
     assert (m_parser_vars.get());
     
+    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+    
     clang::ASTContext *context(m_parser_vars->m_exe_ctx->target->GetScratchClangASTContext()->getASTContext());
     
     TypeFromUser user_type(ClangASTContext::CopyType(context, 
@@ -219,6 +226,24 @@
     if (!var_sp)
         return false;
     
+    if (is_result)
+        var_sp->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry;
+    else
+        var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget; // explicitly-declared persistent variables should persist
+    
+    if (is_lvalue)
+    {
+        var_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference;
+    }
+    else
+    {
+        var_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
+        var_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
+    }
+    
+    if (log)
+        log->Printf("Created persistent variable with flags 0x%hx", var_sp->m_flags);
+    
     var_sp->EnableParserVars();
     
     var_sp->m_parser_vars->m_named_decl = decl;
@@ -441,7 +466,7 @@
     
     m_material_vars->m_process = exe_ctx.process;
     
-    bool result = DoMaterialize(false, exe_ctx, NULL, err);
+    bool result = DoMaterialize(false /* dematerialize */, exe_ctx, NULL, err);
     
     if (result)
         struct_address = m_material_vars->m_materialized_location;
@@ -740,9 +765,8 @@
                 
                 if (!DoMaterializeOneVariable (dematerialize, 
                                                exe_ctx, 
-                                               sym_ctx, 
-                                               member_sp->GetName(), 
-                                               member_sp->GetTypeFromUser(), 
+                                               sym_ctx,
+                                               member_sp,
                                                m_material_vars->m_materialized_location + member_sp->m_jit_vars->m_offset, 
                                                err))
                     return false;
@@ -754,20 +778,21 @@
             // with with a '$' character...
             if (member_sp->GetName().AsCString ("!")[0] == '$' && persistent_vars.ContainsVariable(member_sp))
             {
+                bool keep_this_in_memory = false;
+                
                 if (member_sp->GetName() == m_struct_vars->m_result_name)
                 {
-                    if (!dematerialize)
-                        continue;
-                    
                     if (log)
                         log->PutCString("Found result member in the struct");
-                    
+
                     if (result_sp_ptr)
                         *result_sp_ptr = member_sp;
+                    
+                    keep_this_in_memory = m_keep_result_in_memory;
                 }
 
                 if (!DoMaterializeOnePersistentVariable (dematerialize, 
-                                                         exe_ctx, 
+                                                         exe_ctx,
                                                          member_sp, 
                                                          m_material_vars->m_materialized_location + member_sp->m_jit_vars->m_offset, 
                                                          err))
@@ -784,6 +809,63 @@
     return true;
 }
 
+static bool WriteAddressInto
+(
+    ExecutionContext &exe_ctx,
+    lldb::addr_t target,
+    lldb::addr_t address,
+    Error &err
+)
+{
+    size_t pointer_byte_size = exe_ctx.process->GetAddressByteSize();
+    
+    StreamString str (0 | Stream::eBinary,
+                      pointer_byte_size,
+                      exe_ctx.process->GetByteOrder());
+    
+    switch (pointer_byte_size)
+    {
+        default:
+            assert(!"Unhandled byte size");
+        case 4:
+        {
+            uint32_t address32 = address & 0xffffffffll;
+            str.PutRawBytes(&address32, sizeof(address32), eByteOrderHost, eByteOrderInvalid);
+        }
+        break;
+        case 8:
+        {
+            uint64_t address64 = address;
+            str.PutRawBytes(&address64, sizeof(address64), eByteOrderHost, eByteOrderInvalid);
+        }
+        break;
+    }
+        
+    return (exe_ctx.process->WriteMemory (target, str.GetData(), pointer_byte_size, err) == pointer_byte_size);
+}
+
+static lldb::addr_t ReadAddressFrom
+(
+    ExecutionContext &exe_ctx,
+    lldb::addr_t source,
+    Error &err
+)
+{
+    size_t pointer_byte_size = exe_ctx.process->GetAddressByteSize();
+
+    DataBufferHeap *buf = new DataBufferHeap(pointer_byte_size, 0);
+    DataBufferSP buf_sp(buf);
+    
+    if (exe_ctx.process->ReadMemory (source, buf->GetBytes(), pointer_byte_size, err) != pointer_byte_size)
+        return LLDB_INVALID_ADDRESS;
+        
+    DataExtractor extractor (buf_sp, exe_ctx.process->GetByteOrder(), exe_ctx.process->GetAddressByteSize());
+    
+    uint32_t offset = 0;
+    
+    return (lldb::addr_t)extractor.GetPointer(&offset);
+}
+
 bool
 ClangExpressionDeclMap::DoMaterializeOnePersistentVariable
 (
@@ -794,6 +876,8 @@
     Error &err
 )
 {
+    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
     if (!var_sp)
     {
         err.SetErrorString("Invalid persistent variable");
@@ -808,20 +892,167 @@
     
     Error error;
     
+    lldb::addr_t mem; // The address of a spare memory area used to hold the persistent variable.
+    
     if (dematerialize)
     {
-        var_sp->ValueUpdated ();
-        if (exe_ctx.process->ReadMemory (addr, pvar_data, pvar_byte_size, error) != pvar_byte_size)
+        if (log)
+            log->Printf("Dematerializing persistent variable with flags 0x%hx", var_sp->m_flags);
+        
+        if ((var_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated) ||
+            (var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference))
         {
-            err.SetErrorStringWithFormat ("Couldn't read a composite type from the target: %s", error.AsCString());
+            // Get the location of the target out of the struct.
+            
+            Error read_error;
+            mem = ReadAddressFrom(exe_ctx, addr, read_error);
+            
+            if (mem == LLDB_INVALID_ADDRESS)
+            {
+                err.SetErrorStringWithFormat("Couldn't read address of %s from struct: %s", var_sp->GetName().GetCString(), error.AsCString());
+                return false;
+            }
+            
+            if (var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference &&
+                !var_sp->m_live_sp)
+            {
+                // If the reference comes from the program, then the ClangExpressionVariable's
+                // live variable data hasn't been set up yet.  Do this now.
+                
+                var_sp->m_live_sp.reset(new lldb_private::ValueObjectConstResult(var_sp->GetTypeFromUser().GetASTContext(),
+                                                                                 var_sp->GetTypeFromUser().GetOpaqueQualType(),
+                                                                                 var_sp->GetName(),
+                                                                                 mem,
+                                                                                 lldb::eAddressTypeLoad,
+                                                                                 pvar_byte_size));
+            }
+            
+            if (!var_sp->m_live_sp)
+            {
+                err.SetErrorStringWithFormat("Couldn't find the memory area used to store %s", var_sp->GetName().GetCString());
+                return false;
+            }
+            
+            if (var_sp->m_live_sp->GetValue().GetValueAddressType() != lldb::eAddressTypeLoad)
+            {
+                err.SetErrorStringWithFormat("The address of the memory area for %s is in an incorrect format", var_sp->GetName().GetCString());
+                return false;
+            }
+            
+            if (var_sp->m_flags & ClangExpressionVariable::EVNeedsFreezeDry)
+            {
+                mem = var_sp->m_live_sp->GetValue().GetScalar().ULongLong();
+                
+                if (log)
+                    log->Printf("Dematerializing %s from 0x%llx", var_sp->GetName().GetCString(), (uint64_t)mem);
+                
+                // Read the contents of the spare memory area
+                
+                if (log)
+                    log->Printf("Read");
+                
+                var_sp->ValueUpdated ();
+                if (exe_ctx.process->ReadMemory (mem, pvar_data, pvar_byte_size, error) != pvar_byte_size)
+                {
+                    err.SetErrorStringWithFormat ("Couldn't read a composite type from the target: %s", error.AsCString());
+                    return false;
+                }
+                
+                var_sp->m_flags &= ~ClangExpressionVariable::EVNeedsFreezeDry;
+            }
+            
+            if (var_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation &&
+                !(var_sp->m_flags & ClangExpressionVariable::EVKeepInTarget))
+            {
+                if (m_keep_result_in_memory)
+                {
+                    var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget;
+                }
+                else
+                {
+                    Error deallocate_error = exe_ctx.process->DeallocateMemory(mem);
+                    
+                    if (!err.Success())
+                    {
+                        err.SetErrorStringWithFormat ("Couldn't deallocate memory for %s: %s", var_sp->GetName().GetCString(), deallocate_error.AsCString());
+                        return false;
+                    }
+                }
+            }
+        }
+        else
+        {
+            err.SetErrorStringWithFormat("Persistent variables without separate allocations are not currently supported.");
             return false;
         }
     }
     else 
     {
-        if (exe_ctx.process->WriteMemory (addr, pvar_data, pvar_byte_size, error) != pvar_byte_size)
+        if (log)
+            log->Printf("Materializing persistent variable with flags 0x%hx", var_sp->m_flags);
+        
+        if (var_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation)
+        {
+            // Allocate a spare memory area to store the persistent variable's contents.
+            
+            Error allocate_error;
+            
+            mem = exe_ctx.process->AllocateMemory(pvar_byte_size, 
+                                                  lldb::ePermissionsReadable | lldb::ePermissionsWritable, 
+                                                  allocate_error);
+            
+            if (mem == LLDB_INVALID_ADDRESS)
+            {
+                err.SetErrorStringWithFormat("Couldn't allocate a memory area to store %s: %s", var_sp->GetName().GetCString(), allocate_error.AsCString());
+                return false;
+            }
+            
+            if (log)
+                log->Printf("Allocated %s (0x%llx) sucessfully", var_sp->GetName().GetCString(), mem);
+            
+            // Put the location of the spare memory into the live data of the ValueObject.
+            
+            var_sp->m_live_sp.reset(new lldb_private::ValueObjectConstResult(var_sp->GetTypeFromUser().GetASTContext(),
+                                                                             var_sp->GetTypeFromUser().GetOpaqueQualType(),
+                                                                             var_sp->GetName(),
+                                                                             mem,
+                                                                             lldb::eAddressTypeLoad,
+                                                                             pvar_byte_size));
+            
+            // Clear the flag if the variable will never be deallocated.
+            
+            if (var_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)
+                var_sp->m_flags &= ~ClangExpressionVariable::EVNeedsAllocation;
+            
+            // Write the contents of the variable to the area.
+            
+            if (exe_ctx.process->WriteMemory (mem, pvar_data, pvar_byte_size, error) != pvar_byte_size)
+            {
+                err.SetErrorStringWithFormat ("Couldn't write a composite type to the target: %s", error.AsCString());
+                return false;
+            }
+        }
+        
+        if ((var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference && var_sp->m_live_sp) ||
+            var_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated)
         {
-            err.SetErrorStringWithFormat ("Couldn't write a composite type to the target: %s", error.AsCString());
+            mem = var_sp->m_live_sp->GetValue().GetScalar().ULongLong();
+            
+            // Now write the location of the area into the struct.
+            
+            Error write_error;
+            if (!WriteAddressInto(exe_ctx, addr, mem, write_error))
+            {
+                err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", var_sp->GetName().GetCString(), write_error.AsCString());
+                return false;
+            }
+            
+            if (log)
+                log->Printf("Materialized %s into 0x%llx", var_sp->GetName().GetCString(), (uint64_t)mem);
+        }
+        else if (!var_sp->m_flags & ClangExpressionVariable::EVIsProgramReference)
+        {
+            err.SetErrorStringWithFormat("Persistent variables without separate allocations are not currently supported.");
             return false;
         }
     }
@@ -835,8 +1066,7 @@
     bool dematerialize,
     ExecutionContext &exe_ctx,
     const SymbolContext &sym_ctx,
-    const ConstString &name,
-    TypeFromUser type,
+    ClangExpressionVariableSP &expr_var,
     lldb::addr_t addr, 
     Error &err
 )
@@ -846,6 +1076,11 @@
     if (!exe_ctx.frame || !exe_ctx.process)
         return false;
     
+    // Vital information about the value
+    
+    const ConstString &name(expr_var->GetName());
+    TypeFromUser type(expr_var->GetTypeFromUser());
+    
     Variable *var = FindVariableInScope (*exe_ctx.frame, name, &type);
     
     if (!var)
@@ -869,8 +1104,8 @@
 
     // The size of the type contained in addr
     
-    size_t addr_bit_size = ClangASTType::GetClangTypeBitWidth(type.GetASTContext(), type.GetOpaqueQualType());
-    size_t addr_byte_size = addr_bit_size % 8 ? ((addr_bit_size + 8) / 8) : (addr_bit_size / 8);
+    size_t value_bit_size = ClangASTType::GetClangTypeBitWidth(type.GetASTContext(), type.GetOpaqueQualType());
+    size_t value_byte_size = value_bit_size % 8 ? ((value_bit_size + 8) / 8) : (value_bit_size / 8);
     
     Value::ValueType value_type = location_value->GetValueType();
     
@@ -888,40 +1123,21 @@
         break;
     case Value::eValueTypeLoadAddress:
         {
-            lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
-            
-            DataBufferHeap data;
-            data.SetByteSize(addr_byte_size);
-            
-            lldb::addr_t src_addr;
-            lldb::addr_t dest_addr;
-            
-            if (dematerialize)
-            {
-                src_addr = addr;
-                dest_addr = value_addr;
-            }
-            else
-            {
-                src_addr = value_addr;
-                dest_addr = addr;
-            }
-            
-            Error error;
-            if (exe_ctx.process->ReadMemory (src_addr, data.GetBytes(), addr_byte_size, error) != addr_byte_size)
-            {
-                err.SetErrorStringWithFormat ("Couldn't read %s from the target: %s", name.GetCString(), error.AsCString());
-                return false;
-            }
-            
-            if (exe_ctx.process->WriteMemory (dest_addr, data.GetBytes(), addr_byte_size, error) != addr_byte_size)
+            if (!dematerialize)
             {
-                err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", name.GetCString(), error.AsCString());
-                return false;
+                lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
+                                
+                Error error;
+
+                if (!WriteAddressInto(exe_ctx,
+                                      addr,
+                                      value_addr,
+                                      error))
+                {
+                    err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", name.GetCString(), error.AsCString());
+                    return false;
+                }
             }
-            
-            if (log)
-                log->Printf("Copied from 0x%llx to 0x%llx", (uint64_t)src_addr, (uint64_t)addr);
         }
         break;
     case Value::eValueTypeScalar:
@@ -929,13 +1145,14 @@
             if (location_value->GetContextType() != Value::eContextTypeRegisterInfo)
             {
                 StreamString ss;
-                
                 location_value->Dump(&ss);
                 
                 err.SetErrorStringWithFormat("%s is a scalar of unhandled type: %s", name.GetCString(), ss.GetString().c_str());
                 return false;
             }
             
+            lldb::addr_t mem; // The address of a spare memory area aused to hold the variable.
+            
             lldb::RegisterInfo *register_info = location_value->GetRegisterInfo();
             
             if (!register_info)
@@ -957,6 +1174,22 @@
             
             if (dematerialize)
             {
+                // Get the location of the spare memory area out of the variable's live data.
+                
+                if (!expr_var->m_live_sp)
+                {
+                    err.SetErrorStringWithFormat("Couldn't find the memory area used to store %s", name.GetCString());
+                    return false;
+                }
+                
+                if (expr_var->m_live_sp->GetValue().GetValueAddressType() != lldb::eAddressTypeLoad)
+                {
+                    err.SetErrorStringWithFormat("The address of the memory area for %s is in an incorrect format", name.GetCString());
+                    return false;
+                }
+                
+                mem = expr_var->m_live_sp->GetValue().GetScalar().ULongLong();
+                
                 // Moving from addr into a register
                 //
                 // Case 1: addr_byte_size and register_byte_size are the same
@@ -974,7 +1207,7 @@
                 //   |AABB0000| Register contents [on little-endian hardware]
                 //   |0000AABB| Register contents [on big-endian hardware]
                 
-                if (addr_byte_size > register_byte_size)
+                if (value_byte_size > register_byte_size)
                 {
                     err.SetErrorStringWithFormat("%s is too big to store in %s", name.GetCString(), register_info->name);
                     return false;
@@ -991,14 +1224,14 @@
                     register_offset = 0;
                     break;
                 case lldb::eByteOrderBig:
-                    register_offset = register_byte_size - addr_byte_size;
+                    register_offset = register_byte_size - value_byte_size;
                     break;
                 }
                 
                 DataBufferHeap register_data (register_byte_size, 0);
                 
                 Error error;
-                if (exe_ctx.process->ReadMemory (addr, register_data.GetBytes() + register_offset, addr_byte_size, error) != addr_byte_size)
+                if (exe_ctx.process->ReadMemory (mem, register_data.GetBytes() + register_offset, value_byte_size, error) != value_byte_size)
                 {
                     err.SetErrorStringWithFormat ("Couldn't read %s from the target: %s", name.GetCString(), error.AsCString());
                     return false;
@@ -1011,9 +1244,54 @@
                     err.SetErrorStringWithFormat("Couldn't read %s from %s", name.GetCString(), register_info->name);
                     return false;
                 }
+                
+                // Deallocate the spare area and clear the variable's live data.
+                
+                Error deallocate_error = exe_ctx.process->DeallocateMemory(mem);
+                
+                if (!deallocate_error.Success())
+                {
+                    err.SetErrorStringWithFormat("Couldn't deallocate spare memory area for %s: %s", name.GetCString(), deallocate_error.AsCString());
+                    return false;
+                }
+                
+                expr_var->m_live_sp.reset();
             }
             else
             {
+                // Allocate a spare memory area to place the register's contents into.  This memory area will be pointed to by the slot in the
+                // struct.
+                
+                Error allocate_error;
+                
+                mem = exe_ctx.process->AllocateMemory(value_byte_size, 
+                                                      lldb::ePermissionsReadable | lldb::ePermissionsWritable, 
+                                                      allocate_error);
+                
+                if (mem == LLDB_INVALID_ADDRESS)
+                {
+                    err.SetErrorStringWithFormat("Couldn't allocate a memory area to store %s: %s", name.GetCString(), allocate_error.AsCString());
+                    return false;
+                }
+                
+                // Put the location of the spare memory into the live data of the ValueObject.
+                
+                expr_var->m_live_sp.reset(new lldb_private::ValueObjectConstResult(type.GetASTContext(),
+                                                                                   type.GetOpaqueQualType(),
+                                                                                   name,
+                                                                                   mem,
+                                                                                   lldb::eAddressTypeLoad,
+                                                                                   value_byte_size));
+                
+                // Now write the location of the area into the struct.
+                
+                Error write_error;
+                if (!WriteAddressInto(exe_ctx, addr, mem, write_error))
+                {
+                    err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", name.GetCString(), write_error.AsCString());
+                    return false;
+                }
+                
                 // Moving from a register into addr
                 //
                 // Case 1: addr_byte_size and register_byte_size are the same
@@ -1031,7 +1309,7 @@
                 //   |AABB|     Address contents on little-endian hardware
                 //       |CCDD| Address contents on big-endian hardware
                 
-                if (addr_byte_size > register_byte_size)
+                if (value_byte_size > register_byte_size)
                 {
                     err.SetErrorStringWithFormat("%s is too big to store in %s", name.GetCString(), register_info->name);
                     return false;
@@ -1048,7 +1326,7 @@
                         register_offset = 0;
                         break;
                     case lldb::eByteOrderBig:
-                        register_offset = register_byte_size - addr_byte_size;
+                        register_offset = register_byte_size - value_byte_size;
                         break;
                 }
                 
@@ -1060,7 +1338,7 @@
                     return false;
                 }
                 
-                const void *register_data = register_extractor.GetData(&register_offset, addr_byte_size);
+                const void *register_data = register_extractor.GetData(&register_offset, value_byte_size);
                 
                 if (!register_data)
                 {
@@ -1068,10 +1346,9 @@
                     return false;
                 }
                 
-                Error error;
-                if (exe_ctx.process->WriteMemory (addr, register_data, addr_byte_size, error) != addr_byte_size)
+                if (exe_ctx.process->WriteMemory (mem, register_data, value_byte_size, write_error) != value_byte_size)
                 {
-                    err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", error.AsCString());
+                    err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", write_error.AsCString());
                     return false;
                 }
             }
@@ -1581,7 +1858,7 @@
     if (!var_location)
         return;
     
-    NamedDecl *var_decl = context.AddVarDecl(pt.GetOpaqueQualType());
+    NamedDecl *var_decl = context.AddVarDecl(ClangASTContext::CreateLValueReferenceType(pt.GetASTContext(), pt.GetOpaqueQualType()));
     std::string decl_name(context.m_decl_name.getAsString());
     ConstString entity_name(decl_name.c_str());
     ClangExpressionVariableSP entity(m_found_entities.CreateVariable (entity_name, 
@@ -1619,7 +1896,7 @@
                                                 user_type.GetOpaqueQualType()),
                                 context.GetASTContext());
     
-    NamedDecl *var_decl = context.AddVarDecl(parser_type.GetOpaqueQualType());
+    NamedDecl *var_decl = context.AddVarDecl(ClangASTContext::CreateLValueReferenceType(parser_type.GetASTContext(), parser_type.GetOpaqueQualType()));
     
     pvar_sp->EnableParserVars();
     pvar_sp->m_parser_vars->m_parser_type = parser_type;

Modified: lldb/trunk/source/Expression/ClangExpressionVariable.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionVariable.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionVariable.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionVariable.cpp Thu Jan 13 02:53:35 2011
@@ -28,14 +28,16 @@
 ClangExpressionVariable::ClangExpressionVariable(lldb::ByteOrder byte_order, uint32_t addr_byte_size) :
     m_parser_vars(),
     m_jit_vars (),
-    m_valojb_sp (new ValueObjectConstResult(byte_order, addr_byte_size))
+    m_frozen_sp (new ValueObjectConstResult(byte_order, addr_byte_size)),
+    m_flags (EVNone)
 {
 }
 
 ClangExpressionVariable::ClangExpressionVariable (const lldb::ValueObjectSP &valobj_sp) :
     m_parser_vars(),
     m_jit_vars (),
-    m_valojb_sp (valobj_sp)
+    m_frozen_sp (valobj_sp),
+    m_flags (EVNone)
 {
 }
 
@@ -45,76 +47,76 @@
 size_t 
 ClangExpressionVariable::GetByteSize ()
 {
-    return m_valojb_sp->GetByteSize();
+    return m_frozen_sp->GetByteSize();
 }    
 
 const ConstString &
 ClangExpressionVariable::GetName ()
 {
-    return m_valojb_sp->GetName();
+    return m_frozen_sp->GetName();
 }    
 
 lldb::ValueObjectSP
 ClangExpressionVariable::GetValueObject()
 {
-    return m_valojb_sp;
+    return m_frozen_sp;
 }
 
 lldb::RegisterInfo *
 ClangExpressionVariable::GetRegisterInfo()
 {
-    return m_valojb_sp->GetValue().GetRegisterInfo();
+    return m_frozen_sp->GetValue().GetRegisterInfo();
 }
 
 void
 ClangExpressionVariable::SetRegisterInfo (const lldb::RegisterInfo *reg_info)
 {
-    return m_valojb_sp->GetValue().SetContext (Value::eContextTypeRegisterInfo, const_cast<lldb::RegisterInfo *>(reg_info));
+    return m_frozen_sp->GetValue().SetContext (Value::eContextTypeRegisterInfo, const_cast<lldb::RegisterInfo *>(reg_info));
 }
 
 lldb::clang_type_t
 ClangExpressionVariable::GetClangType()
 {
-    return m_valojb_sp->GetClangType();
+    return m_frozen_sp->GetClangType();
 }    
 
 void
 ClangExpressionVariable::SetClangType(lldb::clang_type_t clang_type)
 {
-    m_valojb_sp->GetValue().SetContext(Value::eContextTypeClangType, clang_type);
+    m_frozen_sp->GetValue().SetContext(Value::eContextTypeClangType, clang_type);
 }    
 
 clang::ASTContext *
 ClangExpressionVariable::GetClangAST()
 {
-    return m_valojb_sp->GetClangAST();
+    return m_frozen_sp->GetClangAST();
 }    
 
 void
 ClangExpressionVariable::SetClangAST (clang::ASTContext *ast)
 {
-    m_valojb_sp->SetClangAST (ast);
+    m_frozen_sp->SetClangAST (ast);
 }
 
 TypeFromUser
 ClangExpressionVariable::GetTypeFromUser()
 {
-    TypeFromUser tfu (m_valojb_sp->GetClangType(), m_valojb_sp->GetClangAST());
+    TypeFromUser tfu (m_frozen_sp->GetClangType(), m_frozen_sp->GetClangAST());
     return tfu;
 }    
 
 uint8_t *
 ClangExpressionVariable::GetValueBytes()
 {
-    const size_t byte_size = m_valojb_sp->GetByteSize();
+    const size_t byte_size = m_frozen_sp->GetByteSize();
     if (byte_size > 0)
     {
-        if (m_valojb_sp->GetDataExtractor().GetByteSize() < byte_size)
+        if (m_frozen_sp->GetDataExtractor().GetByteSize() < byte_size)
         {
-            m_valojb_sp->GetValue().ResizeData(byte_size);
-            m_valojb_sp->GetValue().GetData (m_valojb_sp->GetDataExtractor());
+            m_frozen_sp->GetValue().ResizeData(byte_size);
+            m_frozen_sp->GetValue().GetData (m_frozen_sp->GetDataExtractor());
         }
-        return const_cast<uint8_t *>(m_valojb_sp->GetDataExtractor().GetDataStart());
+        return const_cast<uint8_t *>(m_frozen_sp->GetDataExtractor().GetDataStart());
     }
     return NULL;
 }
@@ -122,12 +124,12 @@
 void
 ClangExpressionVariable::SetName (const ConstString &name)
 {
-    m_valojb_sp->SetName (name);
+    m_frozen_sp->SetName (name);
 }
 
 void
 ClangExpressionVariable::ValueUpdated ()
 {
-    m_valojb_sp->ValueUpdated ();
+    m_frozen_sp->ValueUpdated ();
 }
 

Modified: lldb/trunk/source/Expression/ClangUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUserExpression.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangUserExpression.cpp (original)
+++ lldb/trunk/source/Expression/ClangUserExpression.cpp Thu Jan 13 02:53:35 2011
@@ -144,6 +144,7 @@
 ClangUserExpression::Parse (Stream &error_stream, 
                             ExecutionContext &exe_ctx,
                             TypeFromUser desired_type,
+                            bool keep_result_in_memory,
                             lldb::ClangExpressionVariableSP *const_result)
 {
     lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -248,7 +249,7 @@
     
     m_desired_type = desired_type;
     
-    m_expr_decl_map.reset(new ClangExpressionDeclMap());
+    m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory));
     
     m_expr_decl_map->WillParse(exe_ctx);
     
@@ -398,7 +399,7 @@
 
 ThreadPlan *
 ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
-                                       ExecutionContext &exe_ctx)
+                                                          ExecutionContext &exe_ctx)
 {
     lldb::addr_t struct_address;
             
@@ -460,6 +461,7 @@
 ClangUserExpression::Execute (Stream &error_stream,
                               ExecutionContext &exe_ctx,
                               bool discard_on_error,
+                              bool keep_in_memory,
                               ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me,
                               lldb::ClangExpressionVariableSP &result)
 {
@@ -556,6 +558,7 @@
 lldb::ExecutionResults
 ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, 
                                bool discard_on_error,
+                               bool keep_in_memory,
                                const char *expr_cstr,
                                const char *expr_prefix,
                                lldb::ValueObjectSP &result_valobj_sp)
@@ -619,7 +622,7 @@
     {
         lldb::ClangExpressionVariableSP expr_result;
 
-        if (const_result.get())
+        if (const_result.get() && !keep_in_memory)
         {
             if (log)
                 log->Printf("== [ClangUserExpression::Evaluate] Expression evaluated as a constant ==");
@@ -635,7 +638,8 @@
 
             execution_results = user_expression_sp->Execute (error_stream, 
                                                              exe_ctx, 
-                                                             discard_on_error, 
+                                                             discard_on_error,
+                                                             keep_in_memory,
                                                              user_expression_sp, 
                                                              expr_result);
             

Modified: lldb/trunk/source/Expression/ClangUtilityFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUtilityFunction.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangUtilityFunction.cpp (original)
+++ lldb/trunk/source/Expression/ClangUtilityFunction.cpp Thu Jan 13 02:53:35 2011
@@ -99,7 +99,9 @@
     // Parse the expression
     //
     
-    m_expr_decl_map.reset(new ClangExpressionDeclMap());
+    bool keep_result_in_memory = false;
+    
+    m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory));
     
     m_expr_decl_map->WillParse(exe_ctx);
         

Modified: lldb/trunk/source/Expression/IRForTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRForTarget.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRForTarget.cpp (original)
+++ lldb/trunk/source/Expression/IRForTarget.cpp Thu Jan 13 02:53:35 2011
@@ -43,7 +43,8 @@
     m_func_name(func_name),
     m_resolve_vars(resolve_vars),
     m_const_result(const_result),
-    m_has_side_effects(NULL)
+    m_has_side_effects(false),
+    m_result_is_pointer(false)
 {
 }
 
@@ -153,10 +154,19 @@
          vi != ve;
          ++vi)
     {
+        if (strstr(vi->first(), "$__lldb_expr_result_ptr") &&
+            !strstr(vi->first(), "GV"))
+        {
+            result_name = vi->first();
+            m_result_is_pointer = true;
+            break;
+        }
+        
         if (strstr(vi->first(), "$__lldb_expr_result") &&
             !strstr(vi->first(), "GV")) 
         {
             result_name = vi->first();
+            m_result_is_pointer = false;
             break;
         }
     }
@@ -178,7 +188,7 @@
     {
         if (log)
             log->PutCString("Result variable had no data");
-                
+        
         return false;
     }
         
@@ -240,14 +250,43 @@
     // 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());
-
-    lldb_private::ConstString new_result_name (m_decl_map->GetPersistentResultName());
-    m_decl_map->AddPersistentVariable(result_decl, new_result_name, result_decl_type);
+    lldb_private::TypeFromParser result_decl_type;
+    
+    if (m_result_is_pointer)
+    {
+        clang::QualType pointer_qual_type = result_decl->getType();
+        clang::Type *pointer_type = pointer_qual_type.getTypePtr();
+        clang::PointerType *pointer_pointertype = dyn_cast<clang::PointerType>(pointer_type);
+        
+        if (!pointer_pointertype)
+        {
+            if (log)
+                log->PutCString("Expected result to have pointer type, but it did not");
+            return false;
+        }
+        
+        clang::QualType element_qual_type = pointer_pointertype->getPointeeType();
+        
+        result_decl_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(),
+                                                        &result_decl->getASTContext());
+    }
+    else
+    {
+        result_decl_type = lldb_private::TypeFromParser(result_decl->getType().getAsOpaquePtr(),
+                                                        &result_decl->getASTContext());
+    }
+    
+    m_result_name = m_decl_map->GetPersistentResultName();
+    // If the result is an Lvalue, it is emitted as a pointer; see
+    // ASTResultSynthesizer::SynthesizeBodyResult.
+    m_decl_map->AddPersistentVariable(result_decl, 
+                                      m_result_name, 
+                                      result_decl_type,
+                                      true,
+                                      m_result_is_pointer);
     
     if (log)
-        log->Printf("Creating a new result global: \"%s\"", new_result_name.GetCString());
+        log->Printf("Creating a new result global: \"%s\"", m_result_name.GetCString());
         
     // Construct a new result global and set up its metadata
     
@@ -256,7 +295,7 @@
                                                            false, /* not constant */
                                                            GlobalValue::ExternalLinkage,
                                                            NULL, /* no initializer */
-                                                           new_result_name.GetCString ());
+                                                           m_result_name.GetCString ());
     
     // 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
@@ -307,7 +346,7 @@
         if (!m_has_side_effects)
         {
             MaybeSetConstantResult (initializer, 
-                                    new_result_name, 
+                                    m_result_name, 
                                     result_decl_type);
         }
                 
@@ -800,7 +839,7 @@
     
     StringRef decl_name (decl->getName());
     lldb_private::ConstString persistent_variable_name (decl_name.data(), decl_name.size());
-    if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type))
+    if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type, false, false))
         return false;
     
     GlobalVariable *persistent_global = new GlobalVariable(llvm_module, 
@@ -964,9 +1003,27 @@
             return false;
         }
         
-        clang::QualType qual_type(clang::QualType::getFromOpaquePtr(opaque_type));
+        clang::QualType qual_type;
+        const Type *value_type;
+        
+        if (!name.compare("$__lldb_expr_result"))
+        {
+            // The $__lldb_expr_result name indicates the the return value has allocated as
+            // a static variable.  Per the comment at ASTResultSynthesizer::SynthesizeBodyResult,
+            // accesses to this static variable need to be redirected to the result of dereferencing
+            // a pointer that is passed in as one of the arguments.
+            //
+            // Consequently, when reporting the size of the type, we report a pointer type pointing
+            // to the type of $__lldb_expr_result, not the type itself.
             
-        const Type *value_type = global_variable->getType();
+            qual_type = ast_context->getPointerType(clang::QualType::getFromOpaquePtr(opaque_type));
+            value_type = PointerType::get(global_variable->getType(), 0);
+        }
+        else
+        {
+            qual_type = clang::QualType::getFromOpaquePtr(opaque_type);
+            value_type = global_variable->getType();
+        }
                 
         size_t value_size = (ast_context->getTypeSize(qual_type) + 7) / 8;
         off_t value_alignment = (ast_context->getTypeAlign(qual_type) + 7) / 8;
@@ -1479,12 +1536,31 @@
         
         ConstantInt *offset_int(ConstantInt::getSigned(offset_type, offset));
         GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(argument, offset_int, "", FirstEntryInstruction);
-        BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", FirstEntryInstruction);
+                
+        Value *replacement;
+        
+        // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in cases where the result
+        // variable is an rvalue, we have to synthesize a dereference of the appropriate structure
+        // entry in order to produce the static variable that the AST thinks it is accessing.
+        if (name == m_result_name && !m_result_is_pointer)
+        {
+            BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType()->getPointerTo(), "", FirstEntryInstruction);
         
+            LoadInst *load = new LoadInst(bit_cast, "", FirstEntryInstruction);
+            
+            replacement = load;
+        }
+        else
+        {
+            BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", FirstEntryInstruction);
+
+            replacement = bit_cast;
+        }
+            
         if (Constant *constant = dyn_cast<Constant>(value))
-            UnfoldConstant(constant, bit_cast, FirstEntryInstruction);
+            UnfoldConstant(constant, replacement, FirstEntryInstruction);
         else
-            value->replaceAllUsesWith(bit_cast);
+            value->replaceAllUsesWith(replacement);
         
         if (GlobalVariable *var = dyn_cast<GlobalVariable>(value))
             var->eraseFromParent();
@@ -1507,7 +1583,7 @@
     {
         if (log)
             log->Printf("Couldn't find \"%s()\" in the module", m_func_name.c_str());
-        
+
         return false;
     }
         

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp Thu Jan 13 02:53:35 2011
@@ -859,7 +859,7 @@
     StringExtractorGDBRemote response;
     if (SendPacketAndWaitForResponse (packet, response, timeout_seconds, false))
     {
-        if (!response.IsOKPacket())
+        if (response.IsOKPacket())
             return true;
     }
     return false;

Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Thu Jan 13 02:53:35 2011
@@ -3615,18 +3615,20 @@
 }
 
 clang_type_t
-ClangASTContext::CreateLValueReferenceType (clang_type_t clang_type)
+ClangASTContext::CreateLValueReferenceType (clang::ASTContext *ast,
+                                            clang_type_t clang_type)
 {
     if (clang_type)
-        return getASTContext()->getLValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
+        return ast->getLValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
     return NULL;
 }
 
 clang_type_t
-ClangASTContext::CreateRValueReferenceType (clang_type_t clang_type)
+ClangASTContext::CreateRValueReferenceType (clang::ASTContext *ast,
+                                            clang_type_t clang_type)
 {
     if (clang_type)
-        return getASTContext()->getRValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
+        return ast->getRValueReferenceType (QualType::getFromOpaquePtr(clang_type)).getAsOpaquePtr();
     return NULL;
 }
 

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Thu Jan 13 02:53:35 2011
@@ -709,13 +709,14 @@
                 ExecutionContext exe_ctx;
                 frame_sp->CalculateExecutionContext (exe_ctx);
                 bool unwind_on_error = true;
+                bool keep_in_memory = false;
                 StreamString expr;
                 char path[PATH_MAX];
                 image_spec.GetPath(path, sizeof(path));
                 expr.Printf("dlopen (\"%s\", 2)", path);
                 const char *prefix = "extern \"C\" void* dlopen (const char *path, int mode);\n";
                 lldb::ValueObjectSP result_valobj_sp;
-                ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
+                ClangUserExpression::Evaluate (exe_ctx, keep_in_memory, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
                 if (result_valobj_sp->GetError().Success())
                 {
                     Scalar scalar;
@@ -776,11 +777,12 @@
                         ExecutionContext exe_ctx;
                         frame_sp->CalculateExecutionContext (exe_ctx);
                         bool unwind_on_error = true;
+                        bool keep_in_memory = false;
                         StreamString expr;
                         expr.Printf("dlclose ((void *)0x%llx)", image_addr);
                         const char *prefix = "extern \"C\" int dlclose(void* handle);\n";
                         lldb::ValueObjectSP result_valobj_sp;
-                        ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, expr.GetData(), prefix, result_valobj_sp);
+                        ClangUserExpression::Evaluate (exe_ctx, unwind_on_error, keep_in_memory, expr.GetData(), prefix, result_valobj_sp);
                         if (result_valobj_sp->GetError().Success())
                         {
                             Scalar scalar;

Modified: lldb/trunk/source/Target/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=123371&r1=123370&r2=123371&view=diff
==============================================================================
--- lldb/trunk/source/Target/Target.cpp (original)
+++ lldb/trunk/source/Target/Target.cpp Thu Jan 13 02:53:35 2011
@@ -910,6 +910,7 @@
     const char *expr_cstr,
     StackFrame *frame,
     bool unwind_on_error,
+    bool keep_in_memory,
     lldb::ValueObjectSP &result_valobj_sp
 )
 {
@@ -952,10 +953,32 @@
             const_valobj_sp = result_valobj_sp->CreateConstantValue (exe_ctx.GetBestExecutionContextScope(), 
                                                                      persistent_variable_name);
 
+        lldb::ValueObjectSP live_valobj_sp = result_valobj_sp;
+        
         result_valobj_sp = const_valobj_sp;
 
-        ClangExpressionVariableSP clang_expr_variable_sp(m_persistent_variables.CreatePersistentVariable(result_valobj_sp));
-        assert (clang_expr_variable_sp.get());        
+        ClangExpressionVariableSP clang_expr_variable_sp(m_persistent_variables.CreatePersistentVariable(result_valobj_sp));        
+        assert (clang_expr_variable_sp.get());
+        
+        // Set flags and live data as appropriate
+
+        const Value &result_value = live_valobj_sp->GetValue();
+        
+        switch (result_value.GetValueType())
+        {
+        case Value::eValueTypeHostAddress:
+        case Value::eValueTypeFileAddress:
+            // we don't do anything with these for now
+            break;
+        case Value::eValueTypeScalar:
+            clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
+            clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
+            break;
+        case Value::eValueTypeLoadAddress:
+            clang_expr_variable_sp->m_live_sp = live_valobj_sp;
+            clang_expr_variable_sp->m_flags |= ClangExpressionVariable::EVIsProgramReference;
+            break;
+        }
     }
     else
     {
@@ -976,7 +999,8 @@
             const char *prefix = GetExpressionPrefixContentsAsCString();
         
             execution_results = ClangUserExpression::Evaluate (exe_ctx, 
-                                                               unwind_on_error, 
+                                                               unwind_on_error,
+                                                               keep_in_memory,
                                                                expr_cstr, 
                                                                prefix, 
                                                                result_valobj_sp);





More information about the lldb-commits mailing list