summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
authorJim Ingham <jingham@apple.com>2012-09-27 01:15:29 +0000
committerJim Ingham <jingham@apple.com>2012-09-27 01:15:29 +0000
commit1f51e60b743fe3abadc79b280937554f90a1aadc (patch)
treec80070376163b486313847554c46050b0f334e2a /lldb/source
parent5c8b1cd220ab92350de8245d75373a0e785a42fc (diff)
downloadbcm5719-llvm-1f51e60b743fe3abadc79b280937554f90a1aadc.tar.gz
bcm5719-llvm-1f51e60b743fe3abadc79b280937554f90a1aadc.zip
Implement returning integer values in "thread return" for arm, x86_64 and i386. Also returns
floats & doubles on x86_64. <rdar://problem/8356523> llvm-svn: 164741
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp79
-rw-r--r--lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp87
-rw-r--r--lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp119
-rw-r--r--lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h1
-rw-r--r--lldb/source/Target/Thread.cpp30
5 files changed, 287 insertions, 29 deletions
diff --git a/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
index 565819c6c7a..391ee0fe00a 100644
--- a/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
+++ b/lldb/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
@@ -508,10 +508,83 @@ ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread,
}
Error
-ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value)
+ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
{
- Error return_error("I can't do that yet Jim.");
- return return_error;
+ Error error;
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ clang_type_t value_type = new_value_sp->GetClangType();
+ if (!value_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ clang::ASTContext *ast_context = new_value_sp->GetClangAST();
+ if (!ast_context)
+ {
+ error.SetErrorString ("Null clang AST for return value.");
+ return error;
+ }
+ Thread *thread = frame_sp->GetThread().get();
+
+ bool is_signed;
+ uint32_t count;
+ bool is_complex;
+
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+ bool set_it_simple = false;
+ if (ClangASTContext::IsIntegerType (value_type, is_signed) || ClangASTContext::IsPointerType(value_type))
+ {
+ DataExtractor data;
+ size_t num_bytes = new_value_sp->GetData(data);
+ uint32_t offset = 0;
+ if (num_bytes <= 8)
+ {
+ const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("r0", 0);
+ if (num_bytes <= 4)
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value))
+ set_it_simple = true;
+ }
+ else
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, 4);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value))
+ {
+ const RegisterInfo *r1_info = reg_ctx->GetRegisterInfoByName("r1", 0);
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (r1_info, raw_value))
+ set_it_simple = true;
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
+ }
+ }
+ else if (ClangASTContext::IsFloatingPointType (value_type, count, is_complex))
+ {
+ if (is_complex)
+ error.SetErrorString ("We don't support returning complex values at present");
+ else
+ error.SetErrorString ("We don't support returning float values at present");
+ }
+
+ if (!set_it_simple)
+ error.SetErrorString ("We only support setting simple integer return types at present.");
+
+ return error;
}
bool
diff --git a/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
index 384f0645d40..c2f674b5131 100644
--- a/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
+++ b/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
@@ -687,6 +687,86 @@ ABIMacOSX_i386::GetArgumentValues (Thread &thread,
return true;
}
+Error
+ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+ Error error;
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ clang_type_t value_type = new_value_sp->GetClangType();
+ if (!value_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ clang::ASTContext *ast_context = new_value_sp->GetClangAST();
+ if (!ast_context)
+ {
+ error.SetErrorString ("Null clang AST for return value.");
+ return error;
+ }
+ Thread *thread = frame_sp->GetThread().get();
+
+ bool is_signed;
+ uint32_t count;
+ bool is_complex;
+
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+ bool set_it_simple = false;
+ if (ClangASTContext::IsIntegerType (value_type, is_signed) || ClangASTContext::IsPointerType(value_type))
+ {
+ DataExtractor data;
+ size_t num_bytes = new_value_sp->GetData(data);
+ uint32_t offset = 0;
+ if (num_bytes <= 8)
+ {
+ const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
+ if (num_bytes <= 4)
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value))
+ set_it_simple = true;
+ }
+ else
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, 4);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value))
+ {
+ const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0);
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (edx_info, raw_value))
+ set_it_simple = true;
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
+ }
+ }
+ else if (ClangASTContext::IsFloatingPointType (value_type, count, is_complex))
+ {
+ if (is_complex)
+ error.SetErrorString ("We don't support returning complex values at present");
+ else
+ error.SetErrorString ("We don't support returning float values at present");
+ }
+
+ if (!set_it_simple)
+ error.SetErrorString ("We only support setting simple integer return types at present.");
+
+ return error;
+}
+
ValueObjectSP
ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
ClangASTType &ast_type) const
@@ -774,13 +854,6 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
return return_valobj_sp;
}
-Error
-ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value)
-{
- Error return_error("I can't do that yet Jim.");
- return return_error;
-}
-
bool
ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
{
diff --git a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
index 82963b440df..7a5bd9dec4f 100644
--- a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
+++ b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
@@ -550,6 +550,100 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread,
return true;
}
+Error
+ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+ Error error;
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ clang_type_t value_type = new_value_sp->GetClangType();
+ if (!value_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ clang::ASTContext *ast_context = new_value_sp->GetClangAST();
+ if (!ast_context)
+ {
+ error.SetErrorString ("Null clang AST for return value.");
+ return error;
+ }
+ Thread *thread = frame_sp->GetThread().get();
+
+ bool is_signed;
+ uint32_t count;
+ bool is_complex;
+
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+ bool set_it_simple = false;
+ if (ClangASTContext::IsIntegerType (value_type, is_signed) || ClangASTContext::IsPointerType(value_type))
+ {
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("rax", 0);
+
+ DataExtractor data;
+ size_t num_bytes = new_value_sp->GetData(data);
+ uint32_t offset = 0;
+ if (num_bytes <= 64)
+ {
+ uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (reg_info, raw_value))
+ set_it_simple = true;
+ }
+ else
+ {
+ error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
+ }
+
+ }
+ else if (ClangASTContext::IsFloatingPointType (value_type, count, is_complex))
+ {
+ if (is_complex)
+ error.SetErrorString ("We don't support returning complex values at present");
+ else
+ {
+ 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;
+ DataExtractor data;
+ size_t num_bytes = new_value_sp->GetData(data);
+
+ unsigned char buffer[16];
+ ByteOrder byte_order = data.GetByteOrder();
+ uint32_t return_bytes;
+
+ return_bytes = data.CopyByteOrderedData (0, num_bytes, buffer, 16, byte_order);
+ xmm0_value.SetBytes(buffer, 16, byte_order);
+ reg_ctx->WriteRegister(xmm0_info, xmm0_value);
+ set_it_simple = true;
+ }
+ else
+ {
+ // FIXME - don't know how to do 80 bit long doubles yet.
+ error.SetErrorString ("We don't support returning float values > 64 bits at present");
+ }
+ }
+ }
+
+ if (!set_it_simple)
+ {
+ // Okay we've got a structure or something that doesn't fit in a simple register.
+ // We should figure out where it really goes, but we don't support this yet.
+ error.SetErrorString ("We only support setting simple integer and float return types at present.");
+ }
+
+ return error;
+}
+
+
ValueObjectSP
ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
ClangASTType &ast_type) const
@@ -584,7 +678,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
// 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];
+ uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("rax", 0), 0);
switch (bit_width)
{
@@ -594,27 +688,27 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
return return_valobj_sp;
case 64:
if (is_signed)
- value.GetScalar() = (int64_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0));
+ value.GetScalar() = (int64_t)(raw_value);
else
- value.GetScalar() = (uint64_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0));
+ value.GetScalar() = (uint64_t)(raw_value);
break;
case 32:
if (is_signed)
- value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffffffff);
+ value.GetScalar() = (int32_t)(raw_value & 0xffffffff);
else
- value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffffffff);
+ value.GetScalar() = (uint32_t)(raw_value & 0xffffffff);
break;
case 16:
if (is_signed)
- value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffff);
+ value.GetScalar() = (int16_t)(raw_value & 0xffff);
else
- value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xffff);
+ value.GetScalar() = (uint16_t)(raw_value & 0xffff);
break;
case 8:
if (is_signed)
- value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xff);
+ value.GetScalar() = (int8_t)(raw_value & 0xff);
else
- value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0) & 0xff);
+ value.GetScalar() = (uint8_t)(raw_value & 0xff);
break;
}
}
@@ -959,13 +1053,6 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &ast_type
return return_valobj_sp;
}
-Error
-ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value)
-{
- Error return_error("I can't do that yet Jim.");
- return return_error;
-}
-
bool
ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
{
diff --git a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
index 31c1f843706..9efc2449948 100644
--- a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
+++ b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
@@ -52,6 +52,7 @@ protected:
lldb::ValueObjectSP
GetReturnValueObjectSimple (lldb_private::Thread &thread,
lldb_private::ClangASTType &ast_type) const;
+
public:
virtual lldb::ValueObjectSP
GetReturnValueObjectImpl (lldb_private::Thread &thread,
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index 5cffe2d2624..ee3a8554da7 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -15,6 +15,7 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Host/Host.h"
+#include "lldb/Symbol/Function.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
@@ -1313,14 +1314,37 @@ Thread::ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return
StackFrameSP older_frame_sp = thread->GetStackFrameAtIndex(older_frame_idx);
if (return_value_sp)
- {
- // TODO: coerce the return_value_sp to the type of the function in frame_sp.
-
+ {
lldb::ABISP abi = thread->GetProcess()->GetABI();
if (!abi)
{
return_error.SetErrorString("Could not find ABI to set return value.");
}
+ SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextFunction);
+
+ // FIXME: ValueObject::Cast doesn't currently work correctly, at least not for scalars.
+ // Turn that back on when that works.
+ if (0 && sc.function != NULL)
+ {
+ Type *function_type = sc.function->GetType();
+ if (function_type)
+ {
+ clang_type_t return_type = sc.function->GetReturnClangType();
+ if (return_type)
+ {
+ ClangASTType ast_type (function_type->GetClangAST(), return_type);
+ StreamString s;
+ ast_type.DumpTypeDescription(&s);
+ ValueObjectSP cast_value_sp = return_value_sp->Cast(ast_type);
+ if (cast_value_sp)
+ {
+ cast_value_sp->SetFormat(eFormatHex);
+ return_value_sp = cast_value_sp;
+ }
+ }
+ }
+ }
+
return_error = abi->SetReturnValueObject(older_frame_sp, return_value_sp);
if (!return_error.Success())
return return_error;
OpenPOWER on IntegriCloud