diff options
author | Yao Qi <yao.qi@linaro.org> | 2015-11-13 15:11:58 +0000 |
---|---|---|
committer | Yao Qi <yao.qi@linaro.org> | 2015-11-13 15:11:58 +0000 |
commit | b13c8ab2b93de7fe1adb1ecd307d9078ce299c6e (patch) | |
tree | aff41a9f447fa8472160c6f15bd616f1a89c0b62 /gdb | |
parent | c1862d0f60ee6050e3d4add7bbb1a595b1758473 (diff) | |
download | gdb-b13c8ab2b93de7fe1adb1ecd307d9078ce299c6e.zip gdb-b13c8ab2b93de7fe1adb1ecd307d9078ce299c6e.tar.gz 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.
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/arm-tdep.c | 162 |
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); |