* [PATCH 2/2] PR 19051: support of inferior call with gnu vector support on ARM
2015-11-11 10:54 [PATCH 0/2] PR 19051: support of inferior call with gnu vector support on ARM Yao Qi
@ 2015-11-11 10:54 ` Yao Qi
2015-11-11 10:54 ` [PATCH 1/2] Refactor arm_return_in_memory Yao Qi
2015-11-13 15:13 ` [PATCH 0/2] PR 19051: support of inferior call with gnu vector support on ARM Yao Qi
2 siblings, 0 replies; 4+ messages in thread
From: Yao Qi @ 2015-11-11 10:54 UTC (permalink / raw)
To: gdb-patches
This patch teaches GDB to support gnu vector in inferior calls. As a
result, fails in gdb.base/gnu_vector.exp are fixed. The calling
convention of gnu vector isn't documented in the AAPCS, because it
is the GCC extension. I checked the gcc/config/arm/arm.c, understand
how GCC pass arguments and return values, and do the same in GDB side.
The patch is tested with both hard float and soft float on arm-linux.
gdb:
2015-11-11 Yao Qi <yao.qi@linaro.org>
PR tdep/19051
* arm-tdep.c (arm_type_align): Return the right alignment
value for vector.
(arm_vfp_cprc_sub_candidate): Return true for 64-bit and
128-bit vector types.
(arm_return_in_memory): Handel vector type.
---
gdb/arm-tdep.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 54 insertions(+), 14 deletions(-)
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index f52f03a..83ce926 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -3446,8 +3446,18 @@ arm_type_align (struct type *t)
return TYPE_LENGTH (t);
case TYPE_CODE_ARRAY:
+ if (TYPE_VECTOR (t))
+ {
+ /* Use the natural alignment for vector types (the same for
+ scalar type), but the maximum alignment is 64-bit. */
+ if (TYPE_LENGTH (t) > 8)
+ return 8;
+ else
+ return TYPE_LENGTH (t);
+ }
+ else
+ return arm_type_align (TYPE_TARGET_TYPE (t));
case TYPE_CODE_COMPLEX:
- /* TODO: What about vector types? */
return arm_type_align (TYPE_TARGET_TYPE (t));
case TYPE_CODE_STRUCT:
@@ -3594,21 +3604,44 @@ arm_vfp_cprc_sub_candidate (struct type *t,
case TYPE_CODE_ARRAY:
{
- int count;
- unsigned unitlen;
- count = arm_vfp_cprc_sub_candidate (TYPE_TARGET_TYPE (t), base_type);
- if (count == -1)
- return -1;
- if (TYPE_LENGTH (t) == 0)
+ if (TYPE_VECTOR (t))
{
- gdb_assert (count == 0);
- return 0;
+ /* A 64-bit or 128-bit containerized vector type are VFP
+ CPRCs. */
+ switch (TYPE_LENGTH (t))
+ {
+ case 8:
+ if (*base_type == VFP_CPRC_UNKNOWN)
+ *base_type = VFP_CPRC_VEC64;
+ return 1;
+ case 16:
+ if (*base_type == VFP_CPRC_UNKNOWN)
+ *base_type = VFP_CPRC_VEC128;
+ return 1;
+ default:
+ return -1;
+ }
+ }
+ else
+ {
+ int count;
+ unsigned unitlen;
+
+ count = arm_vfp_cprc_sub_candidate (TYPE_TARGET_TYPE (t),
+ base_type);
+ if (count == -1)
+ return -1;
+ if (TYPE_LENGTH (t) == 0)
+ {
+ gdb_assert (count == 0);
+ return 0;
+ }
+ else if (count == 0)
+ return -1;
+ unitlen = arm_vfp_cprc_unit_length (*base_type);
+ gdb_assert ((TYPE_LENGTH (t) % unitlen) == 0);
+ return TYPE_LENGTH (t) / unitlen;
}
- else if (count == 0)
- return -1;
- unitlen = arm_vfp_cprc_unit_length (*base_type);
- gdb_assert ((TYPE_LENGTH (t) % unitlen) == 0);
- return TYPE_LENGTH (t) / unitlen;
}
break;
@@ -9002,6 +9035,13 @@ arm_return_in_memory (struct gdbarch *gdbarch, struct type *type)
&& TYPE_CODE_ARRAY != code && TYPE_CODE_COMPLEX != code)
return 0;
+ if (TYPE_CODE_ARRAY == code && TYPE_VECTOR (type))
+ {
+ /* Vector values should be returned using ARM registers if they
+ are not over 16 bytes. */
+ return (TYPE_LENGTH (type) > 16);
+ }
+
if (gdbarch_tdep (gdbarch)->arm_abi != ARM_ABI_APCS)
{
/* The AAPCS says all aggregates not larger than a word are returned
--
1.9.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] Refactor arm_return_in_memory
2015-11-11 10:54 [PATCH 0/2] PR 19051: support of inferior call with gnu vector support on ARM Yao Qi
2015-11-11 10:54 ` [PATCH 2/2] " Yao Qi
@ 2015-11-11 10:54 ` Yao Qi
2015-11-13 15:13 ` [PATCH 0/2] PR 19051: support of inferior call with gnu vector support on ARM Yao Qi
2 siblings, 0 replies; 4+ messages in thread
From: Yao Qi @ 2015-11-11 10:54 UTC (permalink / raw)
To: gdb-patches
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-11 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.
---
gdb/arm-tdep.c | 162 ++++++++++++++++++++++++++++++---------------------------
1 file changed, 84 insertions(+), 78 deletions(-)
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 4f8c7f2..f52f03a 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -8991,99 +8991,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
@@ -9238,12 +9245,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);
--
1.9.1
^ permalink raw reply [flat|nested] 4+ messages in thread