omjavaid created this revision.
omjavaid added reviewers: tberghammer, clayborg.
omjavaid added a subscriber: lldb-commits.
Herald added subscribers: rengolin, aemerson.
Arm hard float ABI can use floating point registers for returning structures
containing all 4 or 8 byte floating point elements.
Arm ABI documentation call such structs a Homogeneous Aggregate, which is a
Composite Type where all of the Fundamental Data Types that compose the type
are the same.
With Arm Hard float ABI a Homogeneous Aggregate with a Base Type of a single-
or double-precision floating-point type with one to four Elements can be
returned using register s0-s3 and d0-d3.
This patch updates ABISysV_arm::GetReturnValueObjectImpl to handle these cases.
ReturnValueTestCase passes on armhf based linux target after applying this
patch.
http://reviews.llvm.org/D16975
Files:
source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
Index: source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
===================================================================
--- source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
+++ source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
@@ -587,6 +587,74 @@
}
else
{
+ if (IsArmHardFloat(thread))
+ {
+ CompilerType base_type;
+ const uint32_t homogeneous_count =
compiler_type.IsHomogeneousAggregate (&base_type);
+
+ if (homogeneous_count > 0 && homogeneous_count <= 4)
+ {
+ if (base_type.IsFloatingPointType(float_count, is_complex))
+ {
+ if (!is_complex)
+ {
+ ProcessSP process_sp (thread.GetProcess());
+ ByteOrder byte_order = process_sp->GetByteOrder();
+
+ DataBufferSP data_sp (new
DataBufferHeap(byte_size, 0));
+ const size_t base_byte_size =
base_type.GetByteSize(nullptr);
+ uint32_t data_offset = 0;
+
+ for (uint32_t reg_index = 0; reg_index <
homogeneous_count; reg_index++)
+ {
+ char reg_name[8];
+
+ if (base_byte_size == 4)
+ ::snprintf (reg_name, sizeof(reg_name),
"s%u", reg_index);
+ else if (base_byte_size == 8)
+ ::snprintf (reg_name, sizeof(reg_name),
"d%u", reg_index);
+ else
+ break;
+
+ const RegisterInfo *reg_info =
reg_ctx->GetRegisterInfoByName(reg_name, 0);
+ if (reg_info == NULL)
+ break;
+
+ RegisterValue reg_value;
+ if (!reg_ctx->ReadRegister(reg_info,
reg_value))
+ break;
+
+ // Make sure we have enough room in "data_sp"
+ if ((data_offset + base_byte_size) <=
data_sp->GetByteSize())
+ {
+ Error error;
+ const size_t bytes_copied =
reg_value.GetAsMemoryData (reg_info,
+
data_sp->GetBytes() + data_offset,
+
base_byte_size,
+
byte_order,
+
error);
+ if (bytes_copied != base_byte_size)
+ break;
+
+ data_offset += bytes_copied;
+ }
+ }
+
+ if (data_offset == byte_size)
+ {
+ DataExtractor data;
+ data.SetByteOrder(byte_order);
+
data.SetAddressByteSize(process_sp->GetAddressByteSize());
+ data.SetData(data_sp);
+
+ return ValueObjectConstResult::Create
(&thread, compiler_type, ConstString(""), data);
+ }
+
+ }
+ }
+ }
+ }
+
if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size,
value))
return return_valobj_sp;
}
Index: source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
===================================================================
--- source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
+++ source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
@@ -587,6 +587,74 @@
}
else
{
+ if (IsArmHardFloat(thread))
+ {
+ CompilerType base_type;
+ const uint32_t homogeneous_count = compiler_type.IsHomogeneousAggregate (&base_type);
+
+ if (homogeneous_count > 0 && homogeneous_count <= 4)
+ {
+ if (base_type.IsFloatingPointType(float_count, is_complex))
+ {
+ if (!is_complex)
+ {
+ ProcessSP process_sp (thread.GetProcess());
+ ByteOrder byte_order = process_sp->GetByteOrder();
+
+ DataBufferSP data_sp (new DataBufferHeap(byte_size, 0));
+ const size_t base_byte_size = base_type.GetByteSize(nullptr);
+ uint32_t data_offset = 0;
+
+ for (uint32_t reg_index = 0; reg_index < homogeneous_count; reg_index++)
+ {
+ char reg_name[8];
+
+ if (base_byte_size == 4)
+ ::snprintf (reg_name, sizeof(reg_name), "s%u", reg_index);
+ else if (base_byte_size == 8)
+ ::snprintf (reg_name, sizeof(reg_name), "d%u", reg_index);
+ else
+ break;
+
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name, 0);
+ if (reg_info == NULL)
+ break;
+
+ RegisterValue reg_value;
+ if (!reg_ctx->ReadRegister(reg_info, reg_value))
+ break;
+
+ // Make sure we have enough room in "data_sp"
+ if ((data_offset + base_byte_size) <= data_sp->GetByteSize())
+ {
+ Error error;
+ const size_t bytes_copied = reg_value.GetAsMemoryData (reg_info,
+ data_sp->GetBytes() + data_offset,
+ base_byte_size,
+ byte_order,
+ error);
+ if (bytes_copied != base_byte_size)
+ break;
+
+ data_offset += bytes_copied;
+ }
+ }
+
+ if (data_offset == byte_size)
+ {
+ DataExtractor data;
+ data.SetByteOrder(byte_order);
+ data.SetAddressByteSize(process_sp->GetAddressByteSize());
+ data.SetData(data_sp);
+
+ return ValueObjectConstResult::Create (&thread, compiler_type, ConstString(""), data);
+ }
+
+ }
+ }
+ }
+ }
+
if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size, value))
return return_valobj_sp;
}
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits