aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYao Qi <yao.qi@linaro.org>2015-11-13 15:11:58 +0000
committerYao Qi <yao.qi@linaro.org>2015-11-13 15:11:58 +0000
commitb13c8ab2b93de7fe1adb1ecd307d9078ce299c6e (patch)
treeaff41a9f447fa8472160c6f15bd616f1a89c0b62
parentc1862d0f60ee6050e3d4add7bbb1a595b1758473 (diff)
downloadfsf-binutils-gdb-b13c8ab2b93de7fe1adb1ecd307d9078ce299c6e.zip
fsf-binutils-gdb-b13c8ab2b93de7fe1adb1ecd307d9078ce299c6e.tar.gz
fsf-binutils-gdb-b13c8ab2b93de7fe1adb1ecd307d9078ce299c6e.tar.bz2
Refactor arm_return_in_memory
Current arm_return_in_memory isn't friendly to adding new things in it. Moreover, a lot of stuff are about APCS, which is not used nowadays (AAPCS is being used). This patch is to refactor arm_return_in_memory, so that some code can be shared for both APCS and AAPCS at the beginning of arm_return_in_memory, and then each ABI (APCS and AAPCS) are processed separately. gdb: 2015-11-13 Yao Qi <yao.qi@linaro.org> * arm-tdep.c (arm_return_in_memory): Rewrite it. (arm_return_value): Call arm_return_in_memory for TYPE_CODE_COMPLEX.
-rw-r--r--gdb/ChangeLog6
-rw-r--r--gdb/arm-tdep.c162
2 files changed, 90 insertions, 78 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index f21cf2e..a4e73e0 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2015-11-13 Yao Qi <yao.qi@linaro.org>
+
+ * arm-tdep.c (arm_return_in_memory): Rewrite it.
+ (arm_return_value): Call arm_return_in_memory for
+ TYPE_CODE_COMPLEX.
+
2015-11-12 Yao Qi <yao.qi@linaro.org>
* arm-tdep.c (push_stack_item): Change contents type to
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 4a8d03b2..c8b665a 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -8989,99 +8989,106 @@ arm_extract_return_value (struct type *type, struct regcache *regs,
static int
arm_return_in_memory (struct gdbarch *gdbarch, struct type *type)
{
- int nRc;
enum type_code code;
type = check_typedef (type);
- /* In the ARM ABI, "integer" like aggregate types are returned in
- registers. For an aggregate type to be integer like, its size
- must be less than or equal to INT_REGISTER_SIZE and the
- offset of each addressable subfield must be zero. Note that bit
- fields are not addressable, and all addressable subfields of
- unions always start at offset zero.
-
- This function is based on the behaviour of GCC 2.95.1.
- See: gcc/arm.c: arm_return_in_memory() for details.
-
- Note: All versions of GCC before GCC 2.95.2 do not set up the
- parameters correctly for a function returning the following
- structure: struct { float f;}; This should be returned in memory,
- not a register. Richard Earnshaw sent me a patch, but I do not
- know of any way to detect if a function like the above has been
- compiled with the correct calling convention. */
+ /* Simple, non-aggregate types (ie not including vectors and
+ complex) are always returned in a register (or registers). */
+ code = TYPE_CODE (type);
+ if (TYPE_CODE_STRUCT != code && TYPE_CODE_UNION != code
+ && TYPE_CODE_ARRAY != code && TYPE_CODE_COMPLEX != code)
+ return 0;
- /* All aggregate types that won't fit in a register must be returned
- in memory. */
- if (TYPE_LENGTH (type) > INT_REGISTER_SIZE)
+ if (gdbarch_tdep (gdbarch)->arm_abi != ARM_ABI_APCS)
{
+ /* The AAPCS says all aggregates not larger than a word are returned
+ in a register. */
+ if (TYPE_LENGTH (type) <= INT_REGISTER_SIZE)
+ return 0;
+
return 1;
}
+ else
+ {
+ int nRc;
- /* The AAPCS says all aggregates not larger than a word are returned
- in a register. */
- if (gdbarch_tdep (gdbarch)->arm_abi != ARM_ABI_APCS)
- return 0;
+ /* All aggregate types that won't fit in a register must be returned
+ in memory. */
+ if (TYPE_LENGTH (type) > INT_REGISTER_SIZE)
+ return 1;
- /* The only aggregate types that can be returned in a register are
- structs and unions. Arrays must be returned in memory. */
- code = TYPE_CODE (type);
- if ((TYPE_CODE_STRUCT != code) && (TYPE_CODE_UNION != code))
- {
- return 1;
- }
+ /* In the ARM ABI, "integer" like aggregate types are returned in
+ registers. For an aggregate type to be integer like, its size
+ must be less than or equal to INT_REGISTER_SIZE and the
+ offset of each addressable subfield must be zero. Note that bit
+ fields are not addressable, and all addressable subfields of
+ unions always start at offset zero.
- /* Assume all other aggregate types can be returned in a register.
- Run a check for structures, unions and arrays. */
- nRc = 0;
+ This function is based on the behaviour of GCC 2.95.1.
+ See: gcc/arm.c: arm_return_in_memory() for details.
- if ((TYPE_CODE_STRUCT == code) || (TYPE_CODE_UNION == code))
- {
- int i;
- /* Need to check if this struct/union is "integer" like. For
- this to be true, its size must be less than or equal to
- INT_REGISTER_SIZE and the offset of each addressable
- subfield must be zero. Note that bit fields are not
- addressable, and unions always start at offset zero. If any
- of the subfields is a floating point type, the struct/union
- cannot be an integer type. */
-
- /* For each field in the object, check:
- 1) Is it FP? --> yes, nRc = 1;
- 2) Is it addressable (bitpos != 0) and
- not packed (bitsize == 0)?
- --> yes, nRc = 1
- */
-
- for (i = 0; i < TYPE_NFIELDS (type); i++)
- {
- enum type_code field_type_code;
- field_type_code = TYPE_CODE (check_typedef (TYPE_FIELD_TYPE (type,
- i)));
-
- /* Is it a floating point type field? */
- if (field_type_code == TYPE_CODE_FLT)
- {
- nRc = 1;
- break;
- }
+ Note: All versions of GCC before GCC 2.95.2 do not set up the
+ parameters correctly for a function returning the following
+ structure: struct { float f;}; This should be returned in memory,
+ not a register. Richard Earnshaw sent me a patch, but I do not
+ know of any way to detect if a function like the above has been
+ compiled with the correct calling convention. */
+
+ /* Assume all other aggregate types can be returned in a register.
+ Run a check for structures, unions and arrays. */
+ nRc = 0;
- /* If bitpos != 0, then we have to care about it. */
- if (TYPE_FIELD_BITPOS (type, i) != 0)
+ if ((TYPE_CODE_STRUCT == code) || (TYPE_CODE_UNION == code))
+ {
+ int i;
+ /* Need to check if this struct/union is "integer" like. For
+ this to be true, its size must be less than or equal to
+ INT_REGISTER_SIZE and the offset of each addressable
+ subfield must be zero. Note that bit fields are not
+ addressable, and unions always start at offset zero. If any
+ of the subfields is a floating point type, the struct/union
+ cannot be an integer type. */
+
+ /* For each field in the object, check:
+ 1) Is it FP? --> yes, nRc = 1;
+ 2) Is it addressable (bitpos != 0) and
+ not packed (bitsize == 0)?
+ --> yes, nRc = 1
+ */
+
+ for (i = 0; i < TYPE_NFIELDS (type); i++)
{
- /* Bitfields are not addressable. If the field bitsize is
- zero, then the field is not packed. Hence it cannot be
- a bitfield or any other packed type. */
- if (TYPE_FIELD_BITSIZE (type, i) == 0)
+ enum type_code field_type_code;
+
+ field_type_code
+ = TYPE_CODE (check_typedef (TYPE_FIELD_TYPE (type,
+ i)));
+
+ /* Is it a floating point type field? */
+ if (field_type_code == TYPE_CODE_FLT)
{
nRc = 1;
break;
}
+
+ /* If bitpos != 0, then we have to care about it. */
+ if (TYPE_FIELD_BITPOS (type, i) != 0)
+ {
+ /* Bitfields are not addressable. If the field bitsize is
+ zero, then the field is not packed. Hence it cannot be
+ a bitfield or any other packed type. */
+ if (TYPE_FIELD_BITSIZE (type, i) == 0)
+ {
+ nRc = 1;
+ break;
+ }
+ }
}
}
- }
- return nRc;
+ return nRc;
+ }
}
/* Write into appropriate registers a function return value of type
@@ -9236,12 +9243,11 @@ arm_return_value (struct gdbarch *gdbarch, struct value *function,
|| arm_return_in_memory (gdbarch, valtype))
return RETURN_VALUE_STRUCT_CONVENTION;
}
-
- /* AAPCS returns complex types longer than a register in memory. */
- if (tdep->arm_abi != ARM_ABI_APCS
- && TYPE_CODE (valtype) == TYPE_CODE_COMPLEX
- && TYPE_LENGTH (valtype) > INT_REGISTER_SIZE)
- return RETURN_VALUE_STRUCT_CONVENTION;
+ else if (TYPE_CODE (valtype) == TYPE_CODE_COMPLEX)
+ {
+ if (arm_return_in_memory (gdbarch, valtype))
+ return RETURN_VALUE_STRUCT_CONVENTION;
+ }
if (writebuf)
arm_store_return_value (valtype, regcache, writebuf);