aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Hayward <alan.hayward@arm.com>2018-08-29 11:28:10 +0100
committerAlan Hayward <alan.hayward@arm.com>2018-08-29 11:28:10 +0100
commitea92689a179c8c03af2ae46989339336d1dd48cd (patch)
tree69c6572e104d92c82ba4a351e985cd44c29b32d7
parentbc672693ccec6ef2faa057726b06e9515339bb74 (diff)
downloadgdb-ea92689a179c8c03af2ae46989339336d1dd48cd.zip
gdb-ea92689a179c8c03af2ae46989339336d1dd48cd.tar.gz
gdb-ea92689a179c8c03af2ae46989339336d1dd48cd.tar.bz2
Aarch64: Func to detect args passed in float regs
aapcs_is_vfp_call_or_return_candidate is as an eventual replacement for is_hfa_or_hva. This function is based on the GCC code gcc/config/aarch64/aarch64.c:aarch64_vfp_is_call_or_return_candidate () gdb/ * aarch64-tdep.c (HA_MAX_NUM_FLDS): New macro. (aapcs_is_vfp_call_or_return_candidate_1): New function. (aapcs_is_vfp_call_or_return_candidate): Likewise.
-rw-r--r--gdb/ChangeLog6
-rw-r--r--gdb/aarch64-tdep.c141
2 files changed, 147 insertions, 0 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2b64e88..927bca6 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2018-08-29 Alan Hayward <alan.hayward@arm.com>
+
+ * aarch64-tdep.c (HA_MAX_NUM_FLDS): New macro.
+ (aapcs_is_vfp_call_or_return_candidate_1): New function.
+ (aapcs_is_vfp_call_or_return_candidate): Likewise.
+
2018-08-28 Simon Marchi <simon.marchi@polymtl.ca>
PR build/23399
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 62f680e..1933847 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -71,6 +71,10 @@
#define AARCH64_B0_REGNUM (AARCH64_H0_REGNUM + 32)
#define AARCH64_SVE_V0_REGNUM (AARCH64_B0_REGNUM + 32)
+/* A Homogeneous Floating-Point or Short-Vector Aggregate may have at most
+ four members. */
+#define HA_MAX_NUM_FLDS 4
+
/* All possible aarch64 target descriptors. */
struct target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1];
@@ -1209,6 +1213,143 @@ is_hfa_or_hva (struct type *ty)
return 0;
}
+/* Worker function for aapcs_is_vfp_call_or_return_candidate.
+
+ Return the number of register required, or -1 on failure.
+
+ When encountering a base element, if FUNDAMENTAL_TYPE is not set then set it
+ to the element, else fail if the type of this element does not match the
+ existing value. */
+
+static int
+aapcs_is_vfp_call_or_return_candidate_1 (struct type *type,
+ struct type **fundamental_type)
+{
+ if (type == nullptr)
+ return -1;
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_FLT:
+ if (TYPE_LENGTH (type) > 16)
+ return -1;
+
+ if (*fundamental_type == nullptr)
+ *fundamental_type = type;
+ else if (TYPE_LENGTH (type) != TYPE_LENGTH (*fundamental_type)
+ || TYPE_CODE (type) != TYPE_CODE (*fundamental_type))
+ return -1;
+
+ return 1;
+
+ case TYPE_CODE_COMPLEX:
+ {
+ struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
+ if (TYPE_LENGTH (target_type) > 16)
+ return -1;
+
+ if (*fundamental_type == nullptr)
+ *fundamental_type = target_type;
+ else if (TYPE_LENGTH (target_type) != TYPE_LENGTH (*fundamental_type)
+ || TYPE_CODE (target_type) != TYPE_CODE (*fundamental_type))
+ return -1;
+
+ return 2;
+ }
+
+ case TYPE_CODE_ARRAY:
+ {
+ if (TYPE_VECTOR (type))
+ {
+ if (TYPE_LENGTH (type) != 8 && TYPE_LENGTH (type) != 16)
+ return -1;
+
+ if (*fundamental_type == nullptr)
+ *fundamental_type = type;
+ else if (TYPE_LENGTH (type) != TYPE_LENGTH (*fundamental_type)
+ || TYPE_CODE (type) != TYPE_CODE (*fundamental_type))
+ return -1;
+
+ return 1;
+ }
+ else
+ {
+ struct type *target_type = TYPE_TARGET_TYPE (type);
+ int count = aapcs_is_vfp_call_or_return_candidate_1
+ (target_type, fundamental_type);
+
+ if (count == -1)
+ return count;
+
+ count *= TYPE_LENGTH (type);
+ return count;
+ }
+ }
+
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ {
+ int count = 0;
+
+ for (int i = 0; i < TYPE_NFIELDS (type); i++)
+ {
+ struct type *member = check_typedef (TYPE_FIELD_TYPE (type, i));
+
+ int sub_count = aapcs_is_vfp_call_or_return_candidate_1
+ (member, fundamental_type);
+ if (sub_count == -1)
+ return -1;
+ count += sub_count;
+ }
+ return count;
+ }
+
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+/* Return true if an argument, whose type is described by TYPE, can be passed or
+ returned in simd/fp registers, providing enough parameter passing registers
+ are available. This is as described in the AAPCS64.
+
+ Upon successful return, *COUNT returns the number of needed registers,
+ *FUNDAMENTAL_TYPE contains the type of those registers.
+
+ Candidate as per the AAPCS64 5.4.2.C is either a:
+ - float.
+ - short-vector.
+ - HFA (Homogeneous Floating-point Aggregate, 4.3.5.1). A Composite type where
+ all the members are floats and has at most 4 members.
+ - HVA (Homogeneous Short-vector Aggregate, 4.3.5.2). A Composite type where
+ all the members are short vectors and has at most 4 members.
+ - Complex (7.1.1)
+
+ Note that HFAs and HVAs can include nested structures and arrays. */
+
+bool
+aapcs_is_vfp_call_or_return_candidate (struct type *type, int *count,
+ struct type **fundamental_type)
+{
+ if (type == nullptr)
+ return false;
+
+ *fundamental_type = nullptr;
+
+ int ag_count = aapcs_is_vfp_call_or_return_candidate_1 (type,
+ fundamental_type);
+
+ if (ag_count > 0 && ag_count <= HA_MAX_NUM_FLDS)
+ {
+ *count = ag_count;
+ return true;
+ }
+ else
+ return false;
+}
+
/* AArch64 function call information structure. */
struct aarch64_call_info
{