diff options
author | Alan Hayward <alan.hayward@arm.com> | 2018-08-29 11:28:10 +0100 |
---|---|---|
committer | Alan Hayward <alan.hayward@arm.com> | 2018-08-29 11:28:10 +0100 |
commit | ea92689a179c8c03af2ae46989339336d1dd48cd (patch) | |
tree | 69c6572e104d92c82ba4a351e985cd44c29b32d7 | |
parent | bc672693ccec6ef2faa057726b06e9515339bb74 (diff) | |
download | gdb-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/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/aarch64-tdep.c | 141 |
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 { |