[Lldb-commits] [lldb] r147157 - in /lldb/trunk: include/lldb/Target/ source/Core/ source/Expression/ source/Plugins/ABI/MacOSX-arm/ source/Plugins/ABI/MacOSX-i386/ source/Plugins/ABI/SysV-x86_64/ source/Plugins/Process/Utility/ source/Symbol/ source/Target/ test/functionalities/return-value/

Jim Ingham jingham at apple.com
Thu Dec 22 11:12:41 PST 2011


Author: jingham
Date: Thu Dec 22 13:12:40 2011
New Revision: 147157

URL: http://llvm.org/viewvc/llvm-project?rev=147157&view=rev
Log:
Improve the x86_64 return value decoder to handle most structure returns.
Switch from GetReturnValue, which was hardly ever used, to GetReturnValueObject
which is much more convenient.
Return the "return value object" as a persistent variable if requested.

Added:
    lldb/trunk/test/functionalities/return-value/
    lldb/trunk/test/functionalities/return-value/Makefile
    lldb/trunk/test/functionalities/return-value/TestReturnValue.py
    lldb/trunk/test/functionalities/return-value/call-func.c
Modified:
    lldb/trunk/include/lldb/Target/ABI.h
    lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h
    lldb/trunk/source/Core/Debugger.cpp
    lldb/trunk/source/Expression/ClangFunction.cpp
    lldb/trunk/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
    lldb/trunk/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
    lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
    lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
    lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
    lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
    lldb/trunk/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
    lldb/trunk/source/Symbol/ClangASTContext.cpp
    lldb/trunk/source/Target/ABI.cpp
    lldb/trunk/source/Target/Thread.cpp
    lldb/trunk/source/Target/ThreadPlanCallFunction.cpp
    lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp

Modified: lldb/trunk/include/lldb/Target/ABI.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ABI.h?rev=147157&r1=147156&r2=147157&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ABI.h (original)
+++ lldb/trunk/include/lldb/Target/ABI.h Thu Dec 22 13:12:40 2011
@@ -45,14 +45,19 @@
     GetArgumentValues (Thread &thread,
                        ValueList &values) const = 0;
     
-    virtual bool
-    GetReturnValue (Thread &thread,
-                    Value &value) const = 0;
-                    
-    virtual lldb::ValueObjectSP
+public:
+    lldb::ValueObjectSP
     GetReturnValueObject (Thread &thread,
-                          ClangASTType &type) const;
+                          ClangASTType &type,
+                          bool persistent = true) const;
 
+protected:    
+    // This is the method the ABI will call to actually calculate the return value.
+    // Don't put it in a persistant value object, that will be done by the ABI::GetReturnValueObject.
+    virtual lldb::ValueObjectSP
+    GetReturnValueObjectImpl (Thread &thread,
+                          ClangASTType &type) const = 0;
+public:
     virtual bool
     CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) = 0;
 

Modified: lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h?rev=147157&r1=147156&r2=147157&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h Thu Dec 22 13:12:40 2011
@@ -22,9 +22,13 @@
 
 class ThreadPlanCallFunction : public ThreadPlan
 {
+    // Create a thread plan to call a function at the address passed in the "function"
+    // argument.  If you plan to call GetReturnValueObject, then pass in the 
+    // return type, otherwise just pass in an invalid ClangASTType.
 public:
     ThreadPlanCallFunction (Thread &thread,
                             Address &function,
+                            const ClangASTType &return_type,
                             lldb::addr_t arg,
                             bool stop_other_threads,
                             bool discard_on_error = true,
@@ -33,6 +37,7 @@
 
     ThreadPlanCallFunction (Thread &thread,
                             Address &function,
+                            const ClangASTType &return_type,
                             bool stop_other_threads,
                             bool discard_on_error,
                             lldb::addr_t *arg1_ptr = NULL,
@@ -90,16 +95,10 @@
     // plan is complete, you can call "GetReturnValue()" to retrieve the value
     // that was extracted.
 
-    const lldb::ValueSP &
-    GetReturnValue ()
+    virtual lldb::ValueObjectSP
+    GetReturnValueObject ()
     {
-        return m_return_value_sp;
-    }
-
-    void
-    RequestReturnValue (lldb::ValueSP &return_value_sp)
-    {
-        m_return_value_sp = return_value_sp;
+        return m_return_valobj_sp;
     }
 
     // Return the stack pointer that the function received
@@ -165,7 +164,8 @@
                                                                          // thread plans, but for reporting purposes,
                                                                          // it's nice to know the real stop reason.
                                                                          // This gets set in DoTakedown.
-    lldb::ValueSP                                   m_return_value_sp;  // If this contains a valid pointer, use the ABI to extract values when complete
+    ClangASTType                                    m_return_type;
+    lldb::ValueObjectSP                             m_return_valobj_sp;  // If this contains a valid pointer, use the ABI to extract values when complete
     bool                                            m_takedown_done;    // We want to ensure we only do the takedown once.  This ensures that.
     lldb::addr_t                                    m_stop_address;     // This is the address we stopped at.  Also set in DoTakedown;
 

Modified: lldb/trunk/source/Core/Debugger.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Debugger.cpp?rev=147157&r1=147156&r2=147157&view=diff
==============================================================================
--- lldb/trunk/source/Core/Debugger.cpp (original)
+++ lldb/trunk/source/Core/Debugger.cpp Thu Dec 22 13:12:40 2011
@@ -1709,12 +1709,9 @@
                                                 ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
                                                 if (return_valobj_sp)
                                                 {
-                                                    cstr = return_valobj_sp->GetValueAsCString ();
-                                                    if (cstr && cstr[0])
-                                                    {
-                                                        s.PutCString(cstr);
-                                                        var_success = true;
-                                                    }
+                                                    ValueObject::DumpValueObjectOptions dump_options;
+                                                    ValueObject::DumpValueObject (s, return_valobj_sp.get(), dump_options);
+                                                    var_success = true;
                                                 }
                                             }
                                         }
@@ -2579,7 +2576,7 @@
     MODULE_WITH_FUNC\
     FILE_AND_LINE\
     "{, stop reason = ${thread.stop-reason}}"\
-    "{, return value = ${thread.return-value}}"\
+    "{\\nReturn value: ${thread.return-value}}"\
     "\\n"
 
 //#define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id}"\

Modified: lldb/trunk/source/Expression/ClangFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangFunction.cpp?rev=147157&r1=147156&r2=147157&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangFunction.cpp (original)
+++ lldb/trunk/source/Expression/ClangFunction.cpp Thu Dec 22 13:12:40 2011
@@ -405,6 +405,7 @@
     Address wrapper_address (NULL, func_addr);
     ThreadPlan *new_plan = new ThreadPlanCallFunction (*thread, 
                                                        wrapper_address,
+                                                       ClangASTType(),
                                                        args_addr,
                                                        stop_others, 
                                                        discard_on_error,
@@ -418,7 +419,8 @@
 {
     // Read the return value - it is the last field in the struct:
     // FIXME: How does clang tell us there's no return value?  We need to handle that case.
-    
+    // FIXME: Create our ThreadPlanCallFunction with the return ClangASTType, and then use GetReturnValueObject
+    // to fetch the value.  That way we can fetch any values we need.
     Process *process = exe_ctx.GetProcessPtr();
     
     if (process == NULL)

Modified: lldb/trunk/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp?rev=147157&r1=147156&r2=147157&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp (original)
+++ lldb/trunk/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp Thu Dec 22 13:12:40 2011
@@ -16,6 +16,7 @@
 #include "lldb/Core/RegisterValue.h"
 #include "lldb/Core/Scalar.h"
 #include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/Symbol/ClangASTContext.h"
 #include "lldb/Symbol/UnwindPlan.h"
 #include "lldb/Target/Process.h"
@@ -417,85 +418,92 @@
     return true;
 }
 
-bool
-ABIMacOSX_arm::GetReturnValue (Thread &thread,
-                               Value &value) const
-{
-    switch (value.GetContextType())
+ValueObjectSP
+ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread,
+                               lldb_private::ClangASTType &ast_type) const
+{
+    Value value;
+    ValueObjectSP return_valobj_sp;
+    
+    void *value_type = ast_type.GetOpaqueQualType();
+    if (!value_type) 
+        return return_valobj_sp;
+    
+    clang::ASTContext *ast_context = ast_type.GetASTContext();
+    if (!ast_context)
+        return return_valobj_sp;
+
+    value.SetContext (Value::eContextTypeClangType, value_type);
+            
+    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+    if (!reg_ctx)
+        return return_valobj_sp;
+        
+    bool is_signed;
+    
+    // Get the pointer to the first stack argument so we have a place to start 
+    // when reading data
+    
+    const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfoByName("r0", 0);
+    if (ClangASTContext::IsIntegerType (value_type, is_signed))
     {
-        default:
-            return false;
-        case Value::eContextTypeClangType:
+        size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);
+        
+        switch (bit_width)
         {
-            // Extract the Clang AST context from the PC so that we can figure out type
-            // sizes
-            
-            clang::ASTContext *ast_context = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext();
-            
-            // Get the pointer to the first stack argument so we have a place to start 
-            // when reading data
-            
-            RegisterContext *reg_ctx = thread.GetRegisterContext().get();
-            
-            void *value_type = value.GetClangType();
-            bool is_signed;
-            
-            const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfoByName("r0", 0);
-            if (ClangASTContext::IsIntegerType (value_type, is_signed))
+            default:
+                return return_valobj_sp;
+            case 64:
             {
-                size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);
-                
-                switch (bit_width)
-                {
-                    default:
-                        return false;
-                    case 64:
-                    {
-                        const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0);
-                        uint64_t raw_value;
-                        raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
-                        raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r1_reg_info, 0) & UINT32_MAX)) << 32;
-                        if (is_signed)
-                            value.GetScalar() = (int64_t)raw_value;
-                        else
-                            value.GetScalar() = (uint64_t)raw_value;
-                    }
-                        break;
-                    case 32:
-                        if (is_signed)
-                            value.GetScalar() = (int32_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX);
-                        else
-                            value.GetScalar() = (uint32_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX);
-                        break;
-                    case 16:
-                        if (is_signed)
-                            value.GetScalar() = (int16_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX);
-                        else
-                            value.GetScalar() = (uint16_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX);
-                        break;
-                    case 8:
-                        if (is_signed)
-                            value.GetScalar() = (int8_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX);
-                        else
-                            value.GetScalar() = (uint8_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX);
-                        break;
-                }
-            }
-            else if (ClangASTContext::IsPointerType (value_type))
-            {
-                uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
-                value.GetScalar() = ptr;
-            }
-            else
-            {
-                // not handled yet
-                return false;
+                const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0);
+                uint64_t raw_value;
+                raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
+                raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r1_reg_info, 0) & UINT32_MAX)) << 32;
+                if (is_signed)
+                    value.GetScalar() = (int64_t)raw_value;
+                else
+                    value.GetScalar() = (uint64_t)raw_value;
             }
+                break;
+            case 32:
+                if (is_signed)
+                    value.GetScalar() = (int32_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX);
+                else
+                    value.GetScalar() = (uint32_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX);
+                break;
+            case 16:
+                if (is_signed)
+                    value.GetScalar() = (int16_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX);
+                else
+                    value.GetScalar() = (uint16_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX);
+                break;
+            case 8:
+                if (is_signed)
+                    value.GetScalar() = (int8_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX);
+                else
+                    value.GetScalar() = (uint8_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX);
+                break;
         }
-            break;
+    }
+    else if (ClangASTContext::IsPointerType (value_type))
+    {
+        uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
+        value.GetScalar() = ptr;
+    }
+    else
+    {
+        // not handled yet
+        return return_valobj_sp;
     }
     
-    return true;
+    // If we get here, we have a valid Value, so make our ValueObject out of it:
+    
+    return_valobj_sp = ValueObjectConstResult::Create(
+                                    thread.GetStackFrameAtIndex(0).get(),
+                                    ast_type.GetASTContext(),
+                                    value,
+                                    ConstString(""));
+    return return_valobj_sp;
 }
 
 bool

Modified: lldb/trunk/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h?rev=147157&r1=147156&r2=147157&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h (original)
+++ lldb/trunk/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h Thu Dec 22 13:12:40 2011
@@ -41,10 +41,12 @@
     GetArgumentValues (lldb_private::Thread &thread,
                        lldb_private::ValueList &values) const;
     
-    virtual bool
-    GetReturnValue (lldb_private::Thread &thread,
-                    lldb_private::Value &value) const;
+protected:
+    virtual lldb::ValueObjectSP
+    GetReturnValueObjectImpl (lldb_private::Thread &thread,
+                    lldb_private::ClangASTType &ast_type) const;
 
+public:
     virtual bool
     CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
     

Modified: lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp?rev=147157&r1=147156&r2=147157&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp (original)
+++ lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp Thu Dec 22 13:12:40 2011
@@ -15,6 +15,7 @@
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/RegisterValue.h"
 #include "lldb/Core/Scalar.h"
+#include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/Symbol/ClangASTContext.h"
 #include "lldb/Symbol/UnwindPlan.h"
 #include "lldb/Target/Process.h"
@@ -681,87 +682,91 @@
     return true;
 }
 
-bool
-ABIMacOSX_i386::GetReturnValue (Thread &thread,
-                                Value &value) const
-{
-    switch (value.GetContextType())
+ValueObjectSP
+ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
+                                ClangASTType &ast_type) const
+{
+    Value value;
+    ValueObjectSP return_valobj_sp;
+    
+    void *value_type = ast_type.GetOpaqueQualType();
+    if (!value_type) 
+        return return_valobj_sp;
+    
+    clang::ASTContext *ast_context = ast_type.GetASTContext();
+    if (!ast_context)
+        return return_valobj_sp;
+
+    value.SetContext (Value::eContextTypeClangType, value_type);
+    
+    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+        if (!reg_ctx)
+        return return_valobj_sp;
+        
+    bool is_signed;
+            
+    if (ClangASTContext::IsIntegerType (value_type, is_signed))
     {
-        default:
-            return false;
-        case Value::eContextTypeClangType:
+        size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);
+        
+        unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
+        unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
+        
+        switch (bit_width)
         {
-            // Extract the Clang AST context from the PC so that we can figure out type
-            // sizes
-            
-            clang::ASTContext *ast_context = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext();
-            
-            // Get the pointer to the first stack argument so we have a place to start 
-            // when reading data
-            
-            RegisterContext *reg_ctx = thread.GetRegisterContext().get();
-            
-            void *value_type = value.GetClangType();
-            bool is_signed;
-            
-            if (ClangASTContext::IsIntegerType (value_type, is_signed))
-            {
-                size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);
-                
-                unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
-                unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
-                
-                switch (bit_width)
-                {
-                    default:
-                    case 128:
-                        // Scalar can't hold 128-bit literals, so we don't handle this
-                        return false;
-                    case 64:
-                        uint64_t raw_value;
-                        raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
-                        raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32;
-                        if (is_signed)
-                            value.GetScalar() = (int64_t)raw_value;
-                        else
-                            value.GetScalar() = (uint64_t)raw_value;
-                        break;
-                    case 32:
-                        if (is_signed)
-                            value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
-                        else
-                            value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
-                        break;
-                    case 16:
-                        if (is_signed)
-                            value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
-                        else
-                            value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
-                        break;
-                    case 8:
-                        if (is_signed)
-                            value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
-                        else
-                            value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
-                        break;
-                }
-            }
-            else if (ClangASTContext::IsPointerType (value_type))
-            {
-                unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
-                uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
-                value.GetScalar() = ptr;
-            }
-            else
-            {
-                // not handled yet
-                return false;
-            }
+            default:
+            case 128:
+                // Scalar can't hold 128-bit literals, so we don't handle this
+                return return_valobj_sp;
+            case 64:
+                uint64_t raw_value;
+                raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
+                raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32;
+                if (is_signed)
+                    value.GetScalar() = (int64_t)raw_value;
+                else
+                    value.GetScalar() = (uint64_t)raw_value;
+                break;
+            case 32:
+                if (is_signed)
+                    value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
+                else
+                    value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
+                break;
+            case 16:
+                if (is_signed)
+                    value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
+                else
+                    value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
+                break;
+            case 8:
+                if (is_signed)
+                    value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
+                else
+                    value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
+                break;
         }
-            break;
+    }
+    else if (ClangASTContext::IsPointerType (value_type))
+    {
+        unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
+        uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
+        value.GetScalar() = ptr;
+    }
+    else
+    {
+        // not handled yet
+        return return_valobj_sp;
     }
     
-    return true;
+    // If we get here, we have a valid Value, so make our ValueObject out of it:
+    
+    return_valobj_sp = ValueObjectConstResult::Create(
+                                    thread.GetStackFrameAtIndex(0).get(),
+                                    ast_type.GetASTContext(),
+                                    value,
+                                    ConstString(""));
+    return return_valobj_sp;
 }
 
 bool

Modified: lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h?rev=147157&r1=147156&r2=147157&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h (original)
+++ lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h Thu Dec 22 13:12:40 2011
@@ -51,9 +51,12 @@
     GetArgumentValues (lldb_private::Thread &thread,
                        lldb_private::ValueList &values) const;
     
-    virtual bool
-    GetReturnValue (lldb_private::Thread &thread,
-                    lldb_private::Value &value) const;
+protected:
+    virtual lldb::ValueObjectSP
+    GetReturnValueObjectImpl (lldb_private::Thread &thread,
+                    lldb_private::ClangASTType &ast_type) const;
+
+public:
 
     virtual bool
     CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);

Modified: lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp?rev=147157&r1=147156&r2=147157&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp (original)
+++ lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp Thu Dec 22 13:12:40 2011
@@ -17,6 +17,9 @@
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/RegisterValue.h"
 #include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Core/ValueObjectMemory.h"
 #include "lldb/Symbol/ClangASTContext.h"
 #include "lldb/Symbol/UnwindPlan.h"
 #include "lldb/Target/Target.h"
@@ -547,83 +550,404 @@
     return true;
 }
 
-bool
-ABISysV_x86_64::GetReturnValue (Thread &thread,
-                                Value &value) const
+ValueObjectSP
+ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
+                                ClangASTType &ast_type) const
 {
-    switch (value.GetContextType())
+    ValueObjectSP return_valobj_sp;
+    Value value;
+    
+    clang_type_t value_type = ast_type.GetOpaqueQualType();
+    if (!value_type) 
+        return return_valobj_sp;
+    
+    clang::ASTContext *ast_context = ast_type.GetASTContext();
+    if (!ast_context)
+        return return_valobj_sp;
+
+    value.SetContext (Value::eContextTypeClangType, value_type);
+    
+    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+    if (!reg_ctx)
+        return return_valobj_sp;
+    
+    bool is_signed;
+    bool is_complex;
+    uint32_t count;
+
+    if (ClangASTContext::IsIntegerType (value_type, is_signed))
     {
+        // For now, assume that the types in the AST values come from the Target's 
+        // scratch AST.    
+        
+        
+        // Extract the register context so we can read arguments from registers
+        
+        size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);
+        unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
+        
+        switch (bit_width)
+        {
         default:
-            return false;
-        case Value::eContextTypeClangType:
+        case 128:
+            // Scalar can't hold 128-bit literals, so we don't handle this
+            return return_valobj_sp;
+        case 64:
+            if (is_signed)
+                value.GetScalar() = (int64_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0));
+            else
+                value.GetScalar() = (uint64_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0));
+            break;
+        case 32:
+            if (is_signed)
+                value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffffffff);
+            else
+                value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffffffff);
+            break;
+        case 16:
+            if (is_signed)
+                value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffff);
+            else
+                value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffff);
+            break;
+        case 8:
+            if (is_signed)
+                value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xff);
+            else
+                value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xff);
+            break;
+        }
+    }
+    else if (ClangASTContext::IsFloatingPointType(value_type, count, is_complex))
+    {
+        // Don't handle complex yet.
+        if (is_complex)
+            return return_valobj_sp;
+        
+        size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);
+        if (bit_width <= 64)
+        {
+            const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0);
+            RegisterValue xmm0_value;
+            if (reg_ctx->ReadRegister (xmm0_info, xmm0_value))
+            {
+                DataExtractor data;
+                if (xmm0_value.GetData(data))
+                {
+                    uint32_t offset = 0;
+                    switch (bit_width)
+                    {
+                        default:
+                            return return_valobj_sp;
+                        case 32:
+                            value.GetScalar() = (float) data.GetFloat(&offset);
+                            break;
+                        case 64:
+                            value.GetScalar() = (double) data.GetDouble(&offset);
+                            break;
+                    }
+                }
+            }
+        }
+        else if (bit_width == 128)
         {
-            void *value_type = value.GetClangType();
-            bool is_signed;
+            // FIXME: x86_64 returns long doubles in stmm0, which is in some 80 bit long double
+            // format, and so we'll have to write some code to convert that into 128 bit long doubles.
+//            const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("stmm0", 0);
+//            RegisterValue st0_value;
+//            if (reg_ctx->ReadRegister (st0_info, st0_value))
+//            {
+//                DataExtractor data;
+//                if (st0_value.GetData(data))
+//                {
+//                    uint32_t offset = 0;
+//                    value.GetScalar() = (long double) data.GetLongDouble (&offset);
+//                    return true;
+//                }
+//            }
             
-            RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+            return return_valobj_sp;
+        }
+    }
+    else if (ClangASTContext::IsPointerType (value_type))
+    {
+        unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
+        value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0);
+    }
+    else
+    {
+        return return_valobj_sp;
+    }
+    
+    // If we get here, we have a valid Value, so make our ValueObject out of it:
+    
+    return_valobj_sp = ValueObjectConstResult::Create(
+                                    thread.GetStackFrameAtIndex(0).get(),
+                                    ast_type.GetASTContext(),
+                                    value,
+                                    ConstString(""));
+    return return_valobj_sp;
+}
+
+ValueObjectSP
+ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread,
+                      ClangASTType &ast_type) const
+{
+
+    ValueObjectSP return_valobj_sp;
+    
+    return_valobj_sp = GetReturnValueObjectSimple(thread, ast_type);
+    if (return_valobj_sp)
+        return return_valobj_sp;
+    
+    clang_type_t ret_value_type = ast_type.GetOpaqueQualType();
+    if (!ret_value_type) 
+        return return_valobj_sp;
+    
+    clang::ASTContext *ast_context = ast_type.GetASTContext();
+    if (!ast_context)
+        return return_valobj_sp;
+        
+    RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
+    if (!reg_ctx_sp)
+        return return_valobj_sp;
+        
+    size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, ret_value_type);
+    if (ClangASTContext::IsAggregateType(ret_value_type))
+    {
+        Target &target = thread.GetProcess().GetTarget();
+        bool is_memory = true;
+        if (bit_width <= 128)
+        {
+            ByteOrder target_byte_order = target.GetArchitecture().GetByteOrder();
+            DataBufferSP data_sp (new DataBufferHeap(16, 0));
+            DataExtractor return_ext (data_sp, 
+                                      target_byte_order, 
+                                      target.GetArchitecture().GetAddressByteSize());
+                                                           
+            const RegisterInfo *rax_info = reg_ctx_sp->GetRegisterInfoByName("rax", 0);
+            const RegisterInfo *rdx_info = reg_ctx_sp->GetRegisterInfoByName("rdx", 0);
+            const RegisterInfo *xmm0_info = reg_ctx_sp->GetRegisterInfoByName("xmm0", 0);
+            const RegisterInfo *xmm1_info = reg_ctx_sp->GetRegisterInfoByName("xmm1", 0);
             
-            if (!reg_ctx)
-                return false;
+            RegisterValue rax_value, rdx_value, xmm0_value, xmm1_value;
+            reg_ctx_sp->ReadRegister (rax_info, rax_value);
+            reg_ctx_sp->ReadRegister (rdx_info, rdx_value);
+            reg_ctx_sp->ReadRegister (xmm0_info, xmm0_value);
+            reg_ctx_sp->ReadRegister (xmm1_info, xmm1_value);
+
+            DataExtractor rax_data, rdx_data, xmm0_data, xmm1_data;
+            
+            rax_value.GetData(rax_data);
+            rdx_value.GetData(rdx_data);
+            xmm0_value.GetData(xmm0_data);
+            xmm1_value.GetData(xmm1_data);
+            
+            uint32_t fp_bytes = 0;       // Tracks how much of the xmm registers we've consumed so far
+            uint32_t integer_bytes = 0;  // Tracks how much of the rax/rds registers we've consumed so far
+            
+            uint32_t num_children = ClangASTContext::GetNumFields (ast_context, ret_value_type);
             
-            if (ClangASTContext::IsIntegerType (value_type, is_signed))
+            // Since we are in the small struct regime, assume we are not in memory.
+            is_memory = false;
+            
+            for (uint32_t idx = 0; idx < num_children; idx++)
             {
-                // For now, assume that the types in the AST values come from the Target's 
-                // scratch AST.    
+                std::string name;
+                uint32_t field_bit_offset;
+                bool is_signed;
+                bool is_complex;
+                uint32_t count;
                 
-                clang::ASTContext *ast_context = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext();
+                clang_type_t field_clang_type = ClangASTContext::GetFieldAtIndex (ast_context, ret_value_type, idx, name, &field_bit_offset);
+                size_t field_bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, field_clang_type);
+
+                // If there are any unaligned fields, this is stored in memory.
+                if (field_bit_offset % field_bit_width != 0)
+                {
+                    is_memory = true;
+                    break;
+                }
                 
-                // Extract the register context so we can read arguments from registers
+                uint32_t field_byte_width = field_bit_width/8;
+                uint32_t field_byte_offset = field_bit_offset/8;
                 
-                size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);
-                unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
+
+                DataExtractor *copy_from_extractor = NULL;
+                uint32_t       copy_from_offset    = 0;
                 
-                switch (bit_width)
+                if (ClangASTContext::IsIntegerType (field_clang_type, is_signed) || ClangASTContext::IsPointerType (field_clang_type))
                 {
-                default:
-                case 128:
-                    // Scalar can't hold 128-bit literals, so we don't handle this
-                    return false;
-                case 64:
-                    if (is_signed)
-                        value.GetScalar() = (int64_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0));
-                    else
-                        value.GetScalar() = (uint64_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0));
-                    break;
-                case 32:
-                    if (is_signed)
-                        value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffffffff);
-                    else
-                        value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffffffff);
-                    break;
-                case 16:
-                    if (is_signed)
-                        value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffff);
-                    else
-                        value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffff);
-                    break;
-                case 8:
-                    if (is_signed)
-                        value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xff);
+                    if (integer_bytes < 8)
+                    {
+                        if (integer_bytes + field_byte_width <= 8)
+                        {
+                            // This is in RAX, copy from register to our result structure:
+                            copy_from_extractor = &rax_data;
+                            copy_from_offset = integer_bytes;
+                            integer_bytes += field_byte_width;
+                        }
+                        else
+                        {
+                            // The next field wouldn't fit in the remaining space, so we pushed it to rdx.
+                            copy_from_extractor = &rdx_data;
+                            copy_from_offset = 0;
+                            integer_bytes = 8 + field_byte_width;
+                        
+                        }
+                    }
+                    else if (integer_bytes + field_byte_width <= 16)
+                    {
+                        copy_from_extractor = &rdx_data;
+                        copy_from_offset = integer_bytes - 8;
+                        integer_bytes += field_byte_width;
+                    }
                     else
-                        value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xff);
-                    break;
+                    {
+                        // The last field didn't fit.  I can't see how that would happen w/o the overall size being 
+                        // greater than 16 bytes.  For now, return a NULL return value object.
+                        return return_valobj_sp;
+                    }
                 }
+                else if (ClangASTContext::IsFloatingPointType (field_clang_type, count, is_complex))
+                {
+                    // Structs with long doubles are always passed in memory.
+                    if (field_bit_width == 128)
+                    {
+                        is_memory = true;
+                        break;
+                    }
+                    else if (field_bit_width == 64)
+                    {
+                        // These have to be in a single xmm register.
+                        if (fp_bytes == 0)
+                            copy_from_extractor = &xmm0_data;
+                        else
+                            copy_from_extractor = &xmm1_data;
+
+                        copy_from_offset = 0;
+                        fp_bytes += field_byte_width;
+                    }
+                    else if (field_bit_width == 32)
+                    {
+                        // This one is kind of complicated.  If we are in an "eightbyte" with another float, we'll
+                        // be stuffed into an xmm register with it.  If we are in an "eightbyte" with one or more ints,
+                        // then we will be stuffed into the appropriate GPR with them.
+                        bool in_gpr;
+                        if (field_byte_offset % 8 == 0) 
+                        {
+                            // We are at the beginning of one of the eightbytes, so check the next element (if any)
+                            if (idx == num_children - 1)
+                                in_gpr = true;
+                            else
+                            {
+                                uint32_t next_field_bit_offset;
+                                clang_type_t next_field_clang_type = ClangASTContext::GetFieldAtIndex (ast_context, 
+                                                                                                       ret_value_type, 
+                                                                                                       idx + 1, 
+                                                                                                       name, 
+                                                                                                       &next_field_bit_offset);
+                                if (ClangASTContext::IsIntegerType (next_field_clang_type, is_signed))
+                                    in_gpr = true;
+                                else
+                                {
+                                    copy_from_offset = 0;
+                                    in_gpr = false;
+                                }
+                            }
+                                
+                        }
+                        else if (field_byte_offset % 4 == 0)
+                        {
+                            // We are inside of an eightbyte, so see if the field before us is floating point:
+                            // This could happen if somebody put padding in the structure.
+                            if (idx == 0)
+                                in_gpr = false;
+                            else
+                            {
+                                uint32_t prev_field_bit_offset;
+                                clang_type_t prev_field_clang_type = ClangASTContext::GetFieldAtIndex (ast_context, 
+                                                                                                       ret_value_type, 
+                                                                                                       idx - 1, 
+                                                                                                       name, 
+                                                                                                       &prev_field_bit_offset);
+                                if (ClangASTContext::IsIntegerType (prev_field_clang_type, is_signed))
+                                    in_gpr = true;
+                                else
+                                {
+                                    copy_from_offset = 4;
+                                    in_gpr = false;
+                                }
+                            }
+                            
+                        }
+                        else
+                        {
+                            is_memory = true;
+                            continue;
+                        }
+                        
+                        // Okay, we've figured out whether we are in GPR or XMM, now figure out which one.
+                        if (in_gpr)
+                        {
+                            if (integer_bytes < 8)
+                            {
+                                // This is in RAX, copy from register to our result structure:
+                                copy_from_extractor = &rax_data;
+                                copy_from_offset = integer_bytes;
+                                integer_bytes += field_byte_width;
+                            }
+                            else
+                            {
+                                copy_from_extractor = &rdx_data;
+                                copy_from_offset = integer_bytes - 8;
+                                integer_bytes += field_byte_width;
+                            }
+                        }
+                        else
+                        {
+                            if (fp_bytes < 8)
+                                copy_from_extractor = &xmm0_data;
+                            else
+                                copy_from_extractor = &xmm1_data;
+
+                            fp_bytes += field_byte_width;
+                        }
+                    } 
+                }
+                if (!copy_from_extractor)
+                    return return_valobj_sp;
+                    
+                copy_from_extractor->CopyByteOrderedData (copy_from_offset, 
+                                                          field_byte_width, 
+                                                          data_sp->GetBytes() + field_byte_offset, 
+                                                          field_byte_width, 
+                                                          target_byte_order);
             }
-            else if (ClangASTContext::IsPointerType (value_type))
-            {
-                unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
-                value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0);
-            }
-            else
+            
+            if (!is_memory)
             {
-                // not handled yet
-                return false;
+                // The result is in our data buffer.  Let's make a variable object out of it:
+                return_valobj_sp = ValueObjectConstResult::Create (&thread, 
+                                                                   ast_context, 
+                                                                   ret_value_type, 
+                                                                   ConstString(""),
+                                                                   return_ext);
             }
         }
-        break;
+        
+        if (is_memory)
+        {
+            unsigned rax_id = reg_ctx_sp->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
+            lldb::addr_t storage_addr = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0);
+            return_valobj_sp = ValueObjectMemory::Create (&thread,
+                                                          "",
+                                                          Address (storage_addr, NULL),
+                                                          ast_type); 
+        }
     }
-    
-    return true;
+        
+    return return_valobj_sp;
 }
 
 bool

Modified: lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h?rev=147157&r1=147156&r2=147157&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h (original)
+++ lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h Thu Dec 22 13:12:40 2011
@@ -45,10 +45,15 @@
     GetArgumentValues (lldb_private::Thread &thread,
                        lldb_private::ValueList &values) const;
     
-    virtual bool
-    GetReturnValue (lldb_private::Thread &thread,
-                    lldb_private::Value &value) const;
-    
+protected:
+    lldb::ValueObjectSP
+    GetReturnValueObjectSimple (lldb_private::Thread &thread,
+                    lldb_private::ClangASTType &ast_type) const;
+public:    
+    virtual lldb::ValueObjectSP
+    GetReturnValueObjectImpl (lldb_private::Thread &thread,
+                          lldb_private::ClangASTType &type) const;
+
     virtual bool
     CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
     

Modified: lldb/trunk/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp?rev=147157&r1=147156&r2=147157&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp Thu Dec 22 13:12:40 2011
@@ -9,7 +9,7 @@
 
 #include "InferiorCallPOSIX.h"
 #include "lldb/Core/StreamFile.h"
-#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObject.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Process.h"
@@ -70,9 +70,12 @@
             AddressRange mmap_range;
             if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range))
             {
+                ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
+                lldb::clang_type_t clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false);
                 ThreadPlanCallFunction *call_function_thread_plan
                   = new ThreadPlanCallFunction (*thread,
                                                 mmap_range.GetBaseAddress(),
+                                                ClangASTType (clang_ast_context->getASTContext(), clang_void_ptr_type),
                                                 stop_other_threads,
                                                 discard_on_error,
                                                 &addr,
@@ -84,13 +87,6 @@
                 lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
                 if (call_plan_sp)
                 {
-                    ValueSP return_value_sp (new Value);
-                    ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
-                    lldb::clang_type_t clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false);
-                    return_value_sp->SetValueType (Value::eValueTypeScalar);
-                    return_value_sp->SetContext (Value::eContextTypeClangType, clang_void_ptr_type);
-                    call_function_thread_plan->RequestReturnValue (return_value_sp);
-
                     StreamFile error_strm;
                     StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
                     if (frame)
@@ -106,7 +102,8 @@
                                                                           error_strm);
                         if (result == eExecutionCompleted)
                         {
-                            allocated_addr = return_value_sp->GetScalar().ULongLong();
+                            
+                            allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
                             if (process->GetAddressByteSize() == 4)
                             {
                                 if (allocated_addr == UINT32_MAX)
@@ -155,6 +152,7 @@
            {
                lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
                                                                             munmap_range.GetBaseAddress(),
+                                                                            ClangASTType(),
                                                                             stop_other_threads,
                                                                             discard_on_error,
                                                                             &addr,

Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=147157&r1=147156&r2=147157&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Thu Dec 22 13:12:40 2011
@@ -5411,9 +5411,10 @@
     if (builtin_type)
     {
         if (builtin_type->isInteger())
+        {
             is_signed = builtin_type->isSignedInteger();
-        
-        return true;
+            return true;
+        }
     }
     
     return false;

Modified: lldb/trunk/source/Target/ABI.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ABI.cpp?rev=147157&r1=147156&r2=147157&view=diff
==============================================================================
--- lldb/trunk/source/Target/ABI.cpp (original)
+++ lldb/trunk/source/Target/ABI.cpp Thu Dec 22 13:12:40 2011
@@ -12,6 +12,7 @@
 #include "lldb/Core/Value.h"
 #include "lldb/Core/ValueObjectConstResult.h"
 #include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Target/Target.h"
 #include "lldb/Target/Thread.h"
 
 using namespace lldb;
@@ -104,25 +105,69 @@
 
 ValueObjectSP
 ABI::GetReturnValueObject (Thread &thread,
-                          ClangASTType &ast_type) const
+                          ClangASTType &ast_type,
+                          bool persistent) const
 {
     if (!ast_type.IsValid())
         return ValueObjectSP();
         
-    Value ret_value;
-    ret_value.SetContext(Value::eContextTypeClangType, 
-                       ast_type.GetOpaqueQualType());
-    if (GetReturnValue (thread, ret_value))
+    ValueObjectSP return_valobj_sp;
+        
+    return_valobj_sp = GetReturnValueObjectImpl(thread, ast_type);
+    if (!return_valobj_sp)
+        return return_valobj_sp;
+    
+    // Now turn this into a persistent variable.
+    // FIXME: This code is duplicated from Target::EvaluateExpression, and it is used in similar form in a couple
+    // of other places.  Figure out the correct Create function to do all this work.
+    
+    if (persistent)
     {
-        return ValueObjectConstResult::Create(
-                                        thread.GetStackFrameAtIndex(0).get(),
-                                        ast_type.GetASTContext(),
-                                        ret_value,
-                                        ConstString("FunctionReturn"));
+        ClangPersistentVariables& persistent_variables = thread.GetProcess().GetTarget().GetPersistentVariables();
+        ConstString persistent_variable_name (persistent_variables.GetNextPersistentVariableName());
+
+        lldb::ValueObjectSP const_valobj_sp;
+        
+        // Check in case our value is already a constant value
+        if (return_valobj_sp->GetIsConstant())
+        {
+            const_valobj_sp = return_valobj_sp;
+            const_valobj_sp->SetName (persistent_variable_name);
+        }
+        else
+            const_valobj_sp = return_valobj_sp->CreateConstantValue (persistent_variable_name);
+
+        lldb::ValueObjectSP live_valobj_sp = return_valobj_sp;
+        
+        return_valobj_sp = const_valobj_sp;
+
+        ClangExpressionVariableSP clang_expr_variable_sp(persistent_variables.CreatePersistentVariable(return_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;
+        }
+        return_valobj_sp = clang_expr_variable_sp->GetValueObject();
 
     }
-    else
-        return ValueObjectSP();
+    return return_valobj_sp;
 }
 
 

Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=147157&r1=147156&r2=147157&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Thu Dec 22 13:12:40 2011
@@ -861,7 +861,7 @@
                                         bool stop_other_threads,
                                         bool discard_on_error)
 {
-    ThreadPlanSP thread_plan_sp (new ThreadPlanCallFunction (*this, function, arg, stop_other_threads, discard_on_error));
+    ThreadPlanSP thread_plan_sp (new ThreadPlanCallFunction (*this, function, ClangASTType(), arg, stop_other_threads, discard_on_error));
     QueueThreadPlan (thread_plan_sp, abort_other_plans);
     return thread_plan_sp.get();
 }

Modified: lldb/trunk/source/Target/ThreadPlanCallFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanCallFunction.cpp?rev=147157&r1=147156&r2=147157&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanCallFunction.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanCallFunction.cpp Thu Dec 22 13:12:40 2011
@@ -37,6 +37,7 @@
 
 ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
                                                 Address &function,
+                                                const ClangASTType &return_type,
                                                 addr_t arg,
                                                 bool stop_other_threads,
                                                 bool discard_on_error,
@@ -47,6 +48,7 @@
     m_stop_other_threads (stop_other_threads),
     m_function_addr (function),
     m_function_sp (NULL),
+    m_return_type (return_type),
     m_takedown_done (false),
     m_stop_address (LLDB_INVALID_ADDRESS)
 {
@@ -149,6 +151,7 @@
 
 ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
                                                 Address &function,
+                                                const ClangASTType &return_type,
                                                 bool stop_other_threads,
                                                 bool discard_on_error,
                                                 addr_t *arg1_ptr,
@@ -162,6 +165,7 @@
     m_stop_other_threads (stop_other_threads),
     m_function_addr (function),
     m_function_sp(NULL),
+    m_return_type (return_type),
     m_takedown_done (false)
 {
     SetOkayToDiscard (discard_on_error);
@@ -281,13 +285,12 @@
     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
     if (!m_takedown_done)
     {
-        // TODO: how do we tell if all went well?
-        if (m_return_value_sp)
+        const ABI *abi = m_thread.GetProcess().GetABI().get();
+        if (abi && m_return_type.IsValid())
         {
-            const ABI *abi = m_thread.GetProcess().GetABI().get();
-            if (abi)
-                abi->GetReturnValue(m_thread, *m_return_value_sp);
+            m_return_valobj_sp = abi->GetReturnValueObject (m_thread, m_return_type);
         }
+
         if (log)
             log->Printf ("DoTakedown called for thread 0x%4.4llx, m_valid: %d complete: %d.\n", m_thread.GetID(), m_valid, IsPlanComplete());
         m_takedown_done = true;

Modified: lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp?rev=147157&r1=147156&r2=147157&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanCallUserExpression.cpp Thu Dec 22 13:12:40 2011
@@ -44,7 +44,7 @@
                                                 lldb::addr_t *this_arg,
                                                 lldb::addr_t *cmd_arg,
                                                 ClangUserExpression::ClangUserExpressionSP &user_expression_sp) :
-    ThreadPlanCallFunction (thread, function, arg, stop_other_threads, discard_on_error, this_arg, cmd_arg),
+    ThreadPlanCallFunction (thread, function, ClangASTType(), arg, stop_other_threads, discard_on_error, this_arg, cmd_arg),
     m_user_expression_sp (user_expression_sp)
 {
 }

Added: lldb/trunk/test/functionalities/return-value/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/return-value/Makefile?rev=147157&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/return-value/Makefile (added)
+++ lldb/trunk/test/functionalities/return-value/Makefile Thu Dec 22 13:12:40 2011
@@ -0,0 +1,5 @@
+LEVEL = ../../make
+
+C_SOURCES := call-func.c
+
+include $(LEVEL)/Makefile.rules

Added: lldb/trunk/test/functionalities/return-value/TestReturnValue.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/return-value/TestReturnValue.py?rev=147157&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/return-value/TestReturnValue.py (added)
+++ lldb/trunk/test/functionalities/return-value/TestReturnValue.py Thu Dec 22 13:12:40 2011
@@ -0,0 +1,127 @@
+"""
+Test getting return-values correctly when stepping out
+"""
+
+import os, time
+import re
+import unittest2
+import lldb, lldbutil
+from lldbtest import *
+
+class ReturnValueTestCase(TestBase):
+
+    mydir = os.path.join("functionalities", "return-value")
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    @python_api_test
+    def test_with_dsym_python(self):
+        """Test getting return values from stepping out with dsyms."""
+        self.buildDsym()
+        self.do_return_value()
+
+    @python_api_test
+    def test_with_dwarf_python(self):
+        """Test getting return values from stepping out."""
+        self.buildDwarf()
+        self.do_return_value()
+
+    def do_return_value(self):
+        """Test getting return values from stepping out."""
+        exe = os.path.join(os.getcwd(), "a.out")
+        error = lldb.SBError()
+
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target, VALID_TARGET)
+
+        inner_sint_bkpt = target.BreakpointCreateByName("inner_sint", exe)
+        self.assertTrue(inner_sint_bkpt, VALID_BREAKPOINT)
+
+        # Now launch the process, and do not stop at entry point.
+        process = target.LaunchSimple(None, None, os.getcwd())
+
+        self.assertTrue(process, PROCESS_IS_VALID)
+
+        # The stop reason of the thread should be breakpoint.
+        self.assertTrue(process.GetState() == lldb.eStateStopped,
+                        STOPPED_DUE_TO_BREAKPOINT)
+
+        # Now finish, and make sure the return value is correct.
+        thread = lldbutil.get_stopped_thread (process, lldb.eStopReasonBreakpoint)
+
+        thread.StepOut();
+
+        self.assertTrue (process.GetState() == lldb.eStateStopped)
+        self.assertTrue (thread.GetStopReason() == lldb.eStopReasonPlanComplete)
+
+        frame = thread.GetFrameAtIndex(0)
+        fun_name = frame.GetFunctionName()
+        self.assertTrue (fun_name == "outer_sint")
+
+        return_value = thread.GetStopReturnValue()
+        self.assertTrue (return_value.IsValid())
+
+        in_int = frame.FindVariable ("value").GetValueAsSigned(error)
+        self.assertTrue (error.Success())
+        ret_int = return_value.GetValueAsSigned(error)
+        self.assertTrue (error.Success())
+        self.assertTrue (in_int == ret_int)
+
+        # Run again and we will stop in inner_sint the second time outer_sint is called.  
+        #Then test stepping out two frames at once:
+
+        process.Continue()
+        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, inner_sint_bkpt)
+        self.assertTrue(len(thread_list) == 1)
+        thread = thread_list[0]
+
+        frame = thread.GetFrameAtIndex(1)
+        fun_name = frame.GetFunctionName ()
+        self.assertTrue (fun_name == "outer_sint")
+        in_int = frame.FindVariable ("value").GetValueAsSigned(error)
+        self.assertTrue (error.Success())
+
+        thread.StepOutOfFrame (frame)
+
+        self.assertTrue (process.GetState() == lldb.eStateStopped)
+        self.assertTrue (thread.GetStopReason() == lldb.eStopReasonPlanComplete)
+        frame = thread.GetFrameAtIndex(0)
+        fun_name = frame.GetFunctionName()
+        self.assertTrue (fun_name == "main")
+
+        ret_value = thread.GetStopReturnValue()
+        self.assertTrue (return_value.IsValid())
+        ret_int = ret_value.GetValueAsSigned (error)
+        self.assertTrue (error.Success())
+        self.assertTrue (in_int == ret_int)
+        
+        # Now try some simple returns that have different types:
+        inner_float_bkpt = target.BreakpointCreateByName("inner_float", exe)
+        self.assertTrue(inner_float_bkpt, VALID_BREAKPOINT)
+        process.Continue()
+        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, inner_float_bkpt)
+        self.assertTrue (len(thread_list) == 1)
+        thread = thread_list[0]
+
+        frame = thread.GetFrameAtIndex(0)
+        in_value = frame.FindVariable ("value")
+        in_float = float (in_value.GetValue())
+        thread.StepOut()
+
+        self.assertTrue (process.GetState() == lldb.eStateStopped)
+        self.assertTrue (thread.GetStopReason() == lldb.eStopReasonPlanComplete)
+
+        frame = thread.GetFrameAtIndex(0)
+        fun_name = frame.GetFunctionName()
+        self.assertTrue (fun_name == "outer_float")
+
+        return_value = thread.GetStopReturnValue()
+        self.assertTrue (return_value.IsValid())
+        return_float = float (return_value.GetValue())
+
+        self.assertTrue(in_float == return_float)
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/functionalities/return-value/call-func.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/return-value/call-func.c?rev=147157&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/return-value/call-func.c (added)
+++ lldb/trunk/test/functionalities/return-value/call-func.c Thu Dec 22 13:12:40 2011
@@ -0,0 +1,90 @@
+int 
+inner_sint (int value)
+{
+  return value;
+}
+
+int
+outer_sint (int value)
+{
+  return inner_sint (value);
+}
+
+float
+inner_float (float value)
+{
+  return value;
+}
+
+float 
+outer_float (float value)
+{
+  return inner_float(value);
+}
+
+double
+inner_double (double value)
+{
+  return value;
+}
+
+double 
+outer_double (double value)
+{
+  return inner_double(value);
+}
+
+long double
+inner_long_double (long double value)
+{
+  return value;
+}
+
+long double 
+outer_long_double (long double value)
+{
+  return inner_long_double(value);
+}
+
+struct
+large_return_struct
+{
+  long long first_long;
+  long long second_long;
+  long long third_long;
+  long long fourth_long;
+
+};
+
+struct large_return_struct
+return_large_struct (long long first, long long second, long long third, long long fourth)
+{
+  return (struct large_return_struct) {first, second, third, fourth};
+}
+
+int 
+main ()
+{
+  int first_int = 123456;
+  int second_int = 234567;
+
+  outer_sint (first_int);
+  outer_sint (second_int);
+
+  float float_value = 12.34;
+  
+  outer_float (float_value);
+
+  double double_value = -23.45;
+
+  outer_double (double_value);
+
+  long double long_double_value = -3456789.987654321;
+
+  outer_long_double (long_double_value);
+
+  return_large_struct (10, 20, 30, 40);
+
+  return 0;
+  
+}





More information about the lldb-commits mailing list