Hi Jim, Palmer and Andrew: I think this patch is kind of major change for GCC RISC-V port, so I cc all RISC-V gcc maintainer to make sure this change is fine with you guys.
- Motivation of this patch: 1. Sync behavior between clang/llvm. 2. Preparation for -mcpu option support, -mcpu will set -march according the core default arch, however it would be awkward if we only change arch: user need to know the default arch of the core and then set the right ABI, of cause user still can specify arch and abi via -march and -mabi. - This patch has change the behavior for default value of ABI, the ABI will derive from -march if -mabi is not given, which is same behavior as clang/llvm. - So the new rule for the ABI: - Use value from -mabi if the option is present. - Derive ABI from -march if -mabi is not present. - Using default value from `--with-abi` if -mabi and -march are both not present. - Derivative rule: - Using ilp32e E-extension is present. - Using ilp32d or lp64d if D-extension is present. - Otherwise using ilp32 or lp64. gcc/ChangeLog: * common/config/riscv/riscv-common.c: * config/riscv/riscv.h: * doc/invoke.texi gcc/testsuite/ChangeLog: * gcc.target/riscv/implied-abi-1.c: New. * gcc.target/riscv/implied-abi-2.c: Ditto. * gcc.target/riscv/implied-abi-3.c: Ditto. * gcc.target/riscv/implied-abi-4.c: Ditto. * gcc.target/riscv/implied-abi-5.c: Ditto. * gcc.target/riscv/implied-abi-6.c: Ditto. * gcc.target/riscv/implied-abi-7.c: Ditto. * gcc.target/riscv/implied-abi-8.c: Ditto. --- gcc/common/config/riscv/riscv-common.c | 142 +++++++++++++----- gcc/config/riscv/riscv.h | 13 +- gcc/doc/invoke.texi | 9 +- .../gcc.target/riscv/implied-abi-1.c | 10 ++ .../gcc.target/riscv/implied-abi-2.c | 10 ++ .../gcc.target/riscv/implied-abi-3.c | 10 ++ .../gcc.target/riscv/implied-abi-4.c | 10 ++ .../gcc.target/riscv/implied-abi-5.c | 10 ++ .../gcc.target/riscv/implied-abi-6.c | 10 ++ .../gcc.target/riscv/implied-abi-7.c | 10 ++ .../gcc.target/riscv/implied-abi-8.c | 10 ++ 11 files changed, 204 insertions(+), 40 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/implied-abi-1.c create mode 100644 gcc/testsuite/gcc.target/riscv/implied-abi-2.c create mode 100644 gcc/testsuite/gcc.target/riscv/implied-abi-3.c create mode 100644 gcc/testsuite/gcc.target/riscv/implied-abi-4.c create mode 100644 gcc/testsuite/gcc.target/riscv/implied-abi-5.c create mode 100644 gcc/testsuite/gcc.target/riscv/implied-abi-6.c create mode 100644 gcc/testsuite/gcc.target/riscv/implied-abi-7.c create mode 100644 gcc/testsuite/gcc.target/riscv/implied-abi-8.c diff --git a/gcc/common/config/riscv/riscv-common.c b/gcc/common/config/riscv/riscv-common.c index 82c5154b6118..07afc1a365e3 100644 --- a/gcc/common/config/riscv/riscv-common.c +++ b/gcc/common/config/riscv/riscv-common.c @@ -79,7 +79,10 @@ private: /* X-len of m_arch. */ unsigned m_xlen; - riscv_subset_list (const char *, location_t); + /* Silent mode, don't emit error if m_silent_p is true. */ + bool m_silent_p; + + riscv_subset_list (const char *, location_t, bool); const char *parsing_subset_version (const char *, unsigned *, unsigned *, unsigned, unsigned, bool, bool *); @@ -104,7 +107,7 @@ public: unsigned xlen() const {return m_xlen;}; - static riscv_subset_list *parse (const char *, location_t); + static riscv_subset_list *parse (const char *, location_t, bool silent_p); }; @@ -118,8 +121,11 @@ riscv_subset_t::riscv_subset_t () { } -riscv_subset_list::riscv_subset_list (const char *arch, location_t loc) - : m_arch (arch), m_loc (loc), m_head (NULL), m_tail (NULL), m_xlen (0) +riscv_subset_list::riscv_subset_list (const char *arch, + location_t loc, + bool silent_p) + : m_arch (arch), m_loc (loc), m_head (NULL), m_tail (NULL), + m_xlen (0), m_silent_p(silent_p) { } @@ -283,8 +289,9 @@ riscv_subset_list::parsing_subset_version (const char *p, } else { - error_at (m_loc, "%<-march=%s%>: Expect number " - "after %<%dp%>.", m_arch, version); + if (!m_silent_p) + error_at (m_loc, "%<-march=%s%>: Expect number " + "after %<%dp%>.", m_arch, version); return NULL; } } @@ -363,8 +370,9 @@ riscv_subset_list::parse_std_ext (const char *p) if (m_xlen > 32) { - error_at (m_loc, "%<-march=%s%>: rv%de is not a valid base ISA", - m_arch, m_xlen); + if (!m_silent_p) + error_at (m_loc, "%<-march=%s%>: rv%de is not a valid base ISA", + m_arch, m_xlen); return NULL; } break; @@ -386,8 +394,9 @@ riscv_subset_list::parse_std_ext (const char *p) break; default: - error_at (m_loc, "%<-march=%s%>: first ISA subset must be %<e%>, " - "%<i%> or %<g%>", m_arch); + if (!m_silent_p) + error_at (m_loc, "%<-march=%s%>: first ISA subset must be %<e%>, " + "%<i%> or %<g%>", m_arch); return NULL; } @@ -412,13 +421,16 @@ riscv_subset_list::parse_std_ext (const char *p) if (std_ext != *std_exts) { - if (strchr (all_std_exts, std_ext) == NULL) - error_at (m_loc, "%<-march=%s%>: unsupported ISA subset %<%c%>", - m_arch, *p); - else - error_at (m_loc, - "%<-march=%s%>: ISA string is not in canonical order. " - "%<%c%>", m_arch, *p); + if (!m_silent_p) + { + if (strchr (all_std_exts, std_ext) == NULL) + error_at (m_loc, "%<-march=%s%>: unsupported ISA subset %<%c%>", + m_arch, *p); + else + error_at (m_loc, + "%<-march=%s%>: ISA string is not in canonical order. " + "%<%c%>", m_arch, *p); + } return NULL; } @@ -522,8 +534,9 @@ riscv_subset_list::parse_multiletter_ext (const char *p, if (*p != '\0' && *p != '_') { - error_at (m_loc, "%<-march=%s%>: %s must separate with _", - m_arch, ext_type_str); + if (!m_silent_p) + error_at (m_loc, "%<-march=%s%>: %s must separate with _", + m_arch, ext_type_str); return NULL; } } @@ -534,9 +547,9 @@ riscv_subset_list::parse_multiletter_ext (const char *p, /* Parsing arch string to subset list, return NULL if parsing failed. */ riscv_subset_list * -riscv_subset_list::parse (const char *arch, location_t loc) +riscv_subset_list::parse (const char *arch, location_t loc, bool silent_p) { - riscv_subset_list *subset_list = new riscv_subset_list (arch, loc); + riscv_subset_list *subset_list = new riscv_subset_list (arch, loc, silent_p); const char *p = arch; if (strncmp (p, "rv32", 4) == 0) { @@ -550,8 +563,9 @@ riscv_subset_list::parse (const char *arch, location_t loc) } else { - error_at (loc, "%<-march=%s%>: ISA string must begin with rv32 or rv64", - arch); + if (!silent_p) + error_at (loc, "%<-march=%s%>: ISA string must begin with rv32 or rv64", + arch); goto fail; } @@ -587,8 +601,9 @@ riscv_subset_list::parse (const char *arch, location_t loc) if (*p != '\0') { - error_at (loc, "%<-march=%s%>: unexpected ISA string at end: %qs", - arch, p); + if (!silent_p) + error_at (loc, "%<-march=%s%>: unexpected ISA string at end: %qs", + arch, p); goto fail; } @@ -604,18 +619,23 @@ fail: std::string riscv_arch_str (bool version_p) { - gcc_assert (current_subset_list); - return current_subset_list->to_string (version_p); + if (current_subset_list) + return current_subset_list->to_string (version_p); + else + return std::string(); } /* Parse a RISC-V ISA string into an option mask. Must clear or set all arch dependent mask bits, in case more than one -march string is passed. */ static void -riscv_parse_arch_string (const char *isa, int *flags, location_t loc) +riscv_parse_arch_string (const char *isa, + int *flags, + location_t loc, + bool silent_p) { riscv_subset_list *subset_list; - subset_list = riscv_subset_list::parse (isa, loc); + subset_list = riscv_subset_list::parse (isa, loc, silent_p); if (!subset_list) return; @@ -664,7 +684,7 @@ riscv_handle_option (struct gcc_options *opts, switch (decoded->opt_index) { case OPT_march_: - riscv_parse_arch_string (decoded->arg, &opts->x_target_flags, loc); + riscv_parse_arch_string (decoded->arg, &opts->x_target_flags, loc, false); return true; default: @@ -678,13 +698,67 @@ const char * riscv_expand_arch (int argc ATTRIBUTE_UNUSED, const char **argv) { - static char *_arch_buf; gcc_assert (argc == 1); int flags; location_t loc = UNKNOWN_LOCATION; - riscv_parse_arch_string (argv[0], &flags, loc); - _arch_buf = xstrdup (riscv_arch_str (false).c_str ()); - return _arch_buf; + riscv_parse_arch_string (argv[0], &flags, loc, true); + const std::string arch = riscv_arch_str (false); + if (arch.length()) + return xasprintf ("-march=%s", arch.c_str()); + else + return ""; +} + +/* Return -mabi option string accroding CURRENT_SUBSET_LIST, + return empty string if it's NULL. + + Derivative rule: + - Using ilp32e E-extension is present. + - Using ilp32d or lp64d if D-extension is present. + - Otherwise using ilp32 or lp64. */ + +static const char * +riscv_get_mabi_from_current_subset_list () +{ + if (current_subset_list == NULL) + { + return ""; + } + + if (current_subset_list->xlen() == 32) + { + /* We don't have ilp32ef or ilp32ed. */ + if (current_subset_list->lookup ("e")) + return "-mabi=ilp32e"; + + if (current_subset_list->lookup ("d")) + return "-mabi=ilp32d"; + + return "-mabi=ilp32"; + } + else + { + gcc_assert (current_subset_list->xlen() == 64); + + if (current_subset_list->lookup ("d")) + return "-mabi=lp64d"; + + return "-mabi=lp64"; + } +} + +/* Derive default -mabi from -march. */ + +const char * +riscv_implied_abi_from_arch (int argc, const char **argv) +{ + int flags; + location_t loc = UNKNOWN_LOCATION; + + gcc_assert (argc == 1); + + riscv_parse_arch_string (argv[0], &flags, loc, true); + return riscv_get_mabi_from_current_subset_list (); } /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index b7b4a1c88a52..0c37dbd6f877 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -41,18 +41,20 @@ along with GCC; see the file COPYING3. If not see #endif extern const char *riscv_expand_arch (int argc, const char **argv); +extern const char *riscv_implied_abi_from_arch (int argc, const char **argv); # define EXTRA_SPEC_FUNCTIONS \ - { "riscv_expand_arch", riscv_expand_arch }, + { "riscv_expand_arch", riscv_expand_arch }, \ + { "riscv_implied_abi_from_arch", riscv_implied_abi_from_arch }, /* Support for a compile-time default CPU, et cetera. The rules are: --with-arch is ignored if -march is specified. - --with-abi is ignored if -mabi is specified. + --with-abi is ignored if -mabi or -march is specified. --with-tune is ignored if -mtune is specified. */ #define OPTION_DEFAULT_SPECS \ {"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \ {"arch", "%{!march=*:-march=%(VALUE)}" }, \ - {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \ + {"abi", "%{!mabi=*:%{!march=*:-mabi=%(VALUE)}}"}, #ifdef IN_LIBGCC2 #undef TARGET_64BIT @@ -69,8 +71,9 @@ extern const char *riscv_expand_arch (int argc, const char **argv); %(subtarget_asm_spec)" #undef DRIVER_SELF_SPECS -#define DRIVER_SELF_SPECS \ -"%{march=*:-march=%:riscv_expand_arch(%*)}" +#define DRIVER_SELF_SPECS \ +"%{march=*:%:riscv_expand_arch(%*)}" \ +"%{!mabi=*:%{march=*:%:riscv_implied_abi_from_arch(%*)}}" #define TARGET_DEFAULT_CMODEL CM_MEDLOW diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index f623467b7637..c6ba738aa0b7 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -25928,7 +25928,14 @@ allows floating-point values up to 32 bits long to be passed in registers; or @samp{-march=rv64ifd -mabi=lp64}, in which no floating-point arguments will be passed in registers. -The default for this argument is system dependent, users who want a specific +When @option{-mabi=} is not specified, the default value will derived from +@option{-march=}, the rules is using @samp{d} ABI variant if D extension is +enabled, otherwise using soft-float ABI variant even F extension is enabled, +there is an special rule for @samp{rv32e} variant is it always use +@samp{ilp32e}. + +If @option{-march} and @option{-mabi=} both are not specified, the default for +this argument is system dependent, users who want a specific calling convention should specify one explicitly. The valid calling conventions are: @samp{ilp32}, @samp{ilp32f}, @samp{ilp32d}, @samp{lp64}, @samp{lp64f}, and @samp{lp64d}. Some calling conventions are impossible to diff --git a/gcc/testsuite/gcc.target/riscv/implied-abi-1.c b/gcc/testsuite/gcc.target/riscv/implied-abi-1.c new file mode 100644 index 000000000000..0ed81d75fadc --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/implied-abi-1.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-skip-if "-mabi given" { *-*-* } { "-mabi=*" } } */ +/* { dg-options "-O -march=rv32i" } */ +#if !(defined(__riscv_float_abi_soft) && (__riscv_xlen == 32)) +#error "Should be ilp32" +#endif +int main() +{ + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/implied-abi-2.c b/gcc/testsuite/gcc.target/riscv/implied-abi-2.c new file mode 100644 index 000000000000..493990b1cadf --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/implied-abi-2.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-skip-if "-mabi given" { *-*-* } { "-mabi=*" } } */ +/* { dg-options "-O -march=rv32e" } */ +#if !(defined(__riscv_float_abi_soft) && (__riscv_xlen == 32) && defined(__riscv_abi_rve)) +#error "Should be ilp32e" +#endif +int main() +{ + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/implied-abi-3.c b/gcc/testsuite/gcc.target/riscv/implied-abi-3.c new file mode 100644 index 000000000000..09d64793c4e6 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/implied-abi-3.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-skip-if "-mabi given" { *-*-* } { "-mabi=*" } } */ +/* { dg-options "-O -march=rv32if" } */ +#if !(defined(__riscv_float_abi_soft) && (__riscv_xlen == 32)) +#error "Should be ilp32" +#endif +int main() +{ + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/implied-abi-4.c b/gcc/testsuite/gcc.target/riscv/implied-abi-4.c new file mode 100644 index 000000000000..432e5646d098 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/implied-abi-4.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-skip-if "-mabi given" { *-*-* } { "-mabi=*" } } */ +/* { dg-options "-O -march=rv32ifd" } */ +#if !(defined(__riscv_float_abi_double) && (__riscv_xlen == 32)) +#error "Should be ilp32d" +#endif +int main() +{ + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/implied-abi-5.c b/gcc/testsuite/gcc.target/riscv/implied-abi-5.c new file mode 100644 index 000000000000..45e64e91e845 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/implied-abi-5.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-skip-if "-mabi given" { *-*-* } { "-mabi=*" } } */ +/* { dg-options "-O -march=rv64i" } */ +#if !(defined(__riscv_float_abi_soft) && (__riscv_xlen == 64)) +#error "Should be lp64" +#endif +int main() +{ + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/implied-abi-6.c b/gcc/testsuite/gcc.target/riscv/implied-abi-6.c new file mode 100644 index 000000000000..7fe29c6206ca --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/implied-abi-6.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-skip-if "-mabi given" { *-*-* } { "-mabi=*" } } */ +/* { dg-options "-O -march=rv64if" } */ +#if !(defined(__riscv_float_abi_soft) && (__riscv_xlen == 64)) +#error "Should be lp64" +#endif +int main() +{ + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/implied-abi-7.c b/gcc/testsuite/gcc.target/riscv/implied-abi-7.c new file mode 100644 index 000000000000..bb334f5f36cf --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/implied-abi-7.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-skip-if "-mabi given" { *-*-* } { "-mabi=*" } } */ +/* { dg-options "-O -march=rv64ifd" } */ +#if !(defined(__riscv_float_abi_double) && (__riscv_xlen == 64)) +#error "Should be lp64d" +#endif +int main() +{ + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/implied-abi-8.c b/gcc/testsuite/gcc.target/riscv/implied-abi-8.c new file mode 100644 index 000000000000..a48a47366978 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/implied-abi-8.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-skip-if "-mabi given" { *-*-* } { "-mabi=*" } } */ +/* { dg-options "-O -march=rv64ifd -mabi=lp64" } */ +#if !(defined(__riscv_float_abi_soft) && (__riscv_xlen == 64)) +#error "Should be lp64" +#endif +int main() +{ + return 0; +} -- 2.28.0