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
This commit is contained in:
Jim Ingham 2012-09-27 01:15:29 +00:00
parent 5c8b1cd220
commit 1f51e60b74
5 changed files with 287 additions and 29 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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,

View File

@ -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;