From d72ca12b846a9f5c01674b280b1817876c77888f Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Fri, 20 Nov 2020 15:55:58 +0800 Subject: RISC-V: Implement TARGET_COMPUTE_MULTILIB Use TARGET_COMPUTE_MULTILIB to search the multi-lib reuse for riscv*-*-elf*, according following rules: 1. Check ABI is same. 2. Check both has atomic extension or both don't have atomic extension. - Because mix soft and hard atomic operation doesn't make sense and won't work as expect. 3. Check current arch is superset of the target multi-lib arch. - It might result slower performance or larger code size, but it safe to run. 4. Pick most match multi-lib set if more than one multi-lib are pass the above checking. Example for how to select multi-lib: We build code with -march=rv32imaf and -mabi=ilp32, and we have following 5 multi-lib set: 1. rv32ia/ilp32 2. rv32ima/ilp32 3. rv32imf/ilp32 4. rv32imaf/ilp32f 5. rv32imafd/ilp32 The first and second multi-lib is safe to like, 3rd multi-lib can't re-use becasue it don't have atomic extension, which is mismatch according rule 2, and the 4th multi-lib can't re-use too due to the ABI mismatch, the last multi-lib can't use since current arch is not superset of the arch of multi-lib. And emit error if not found suitable multi-lib set, the error message only emit when link with standard libraries. Example for when error will be emitted: $ riscv64-unknown-elf-gcc -print-multi-lib .; rv32i/ilp32;@march=rv32i@mabi=ilp32 rv32im/ilp32;@march=rv32im@mabi=ilp32 rv32iac/ilp32;@march=rv32iac@mabi=ilp32 rv32imac/ilp32;@march=rv32imac@mabi=ilp32 rv32imafc/ilp32f;@march=rv32imafc@mabi=ilp32f rv64imac/lp64;@march=rv64imac@mabi=lp64 // No actual linking, so no error emitted. $ riscv64-unknown-elf-gcc -print-multi-directory -march=rv32ia -mabi=ilp32 . // Link to default libc and libgcc, so check the multi-lib, and emit // error because not found suitable multilib. $ riscv64-unknown-elf-gcc -march=rv32ia -mabi=ilp32 ~/hello.c riscv64-unknown-elf-gcc: fatal error: can't found suitable multilib set for '-march=rv32ia'/'-mabi=ilp32' compilation terminated. // No error emitted, because not link to stdlib. $ riscv64-unknown-elf-gcc -march=rv32ia -mabi=ilp32 ~/hello.c -nostdlib // No error emitted, because compile only. $ riscv64-unknown-elf-gcc -march=rv32ia -mabi=ilp32 ~/hello.c -c gcc/ChangeLog: * common/config/riscv/riscv-common.cc: Include . (struct riscv_multi_lib_info_t): New. (riscv_subset_list::match_score): Ditto. (find_last_appear_switch): Ditto. (prefixed_with): Ditto. (struct multi_lib_info_t): Ditto. (riscv_current_arch_str): Ditto. (riscv_current_abi_str): Ditto. (riscv_multi_lib_info_t::parse): Ditto. (riscv_check_cond): Ditto. (riscv_check_conds): Ditto. (riscv_compute_multilib): Ditto. (TARGET_COMPUTE_MULTILIB): Defined. * config/riscv/elf.h (LIB_SPEC): Call riscv_multi_lib_check if doing link. (RISCV_USE_CUSTOMISED_MULTI_LIB): New. * config/riscv/riscv.h (riscv_multi_lib_check): New. (EXTRA_SPEC_FUNCTIONS): Add riscv_multi_lib_check. * config/riscv/riscv-subset.h (riscv_subset_list::match_score): New. --- gcc/config/riscv/elf.h | 6 +++++- gcc/config/riscv/riscv-subset.h | 2 ++ gcc/config/riscv/riscv.h | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'gcc/config') diff --git a/gcc/config/riscv/elf.h b/gcc/config/riscv/elf.h index f0e865d..f3d767c 100644 --- a/gcc/config/riscv/elf.h +++ b/gcc/config/riscv/elf.h @@ -27,10 +27,14 @@ along with GCC; see the file COPYING3. If not see /* Link against Newlib libraries, because the ELF backend assumes Newlib. Handle the circular dependence between libc and libgloss. */ #undef LIB_SPEC -#define LIB_SPEC "--start-group -lc %{!specs=nosys.specs:-lgloss} --end-group" +#define LIB_SPEC \ + "--start-group -lc %{!specs=nosys.specs:-lgloss} --end-group " \ + "%{!nostartfiles:%{!nodefaultlibs:%{!nolibc:%{!nostdlib:%:riscv_multi_lib_check()}}}}" #undef STARTFILE_SPEC #define STARTFILE_SPEC "crt0%O%s crtbegin%O%s" #undef ENDFILE_SPEC #define ENDFILE_SPEC "crtend%O%s" + +#define RISCV_USE_CUSTOMISED_MULTI_LIB 1 diff --git a/gcc/config/riscv/riscv-subset.h b/gcc/config/riscv/riscv-subset.h index c592650..0bb3a9d 100644 --- a/gcc/config/riscv/riscv-subset.h +++ b/gcc/config/riscv/riscv-subset.h @@ -89,6 +89,8 @@ public: const riscv_subset_t *begin () const {return m_head;}; const riscv_subset_t *end () const {return NULL;}; + + int match_score (riscv_subset_list *) const; }; extern const riscv_subset_list *riscv_current_subset_list (void); diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 3ee5a93..e35aaa7 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -50,11 +50,13 @@ along with GCC; see the file COPYING3. If not see extern const char *riscv_expand_arch (int argc, const char **argv); extern const char *riscv_expand_arch_from_cpu (int argc, const char **argv); extern const char *riscv_default_mtune (int argc, const char **argv); +extern const char *riscv_multi_lib_check (int argc, const char **argv); # define EXTRA_SPEC_FUNCTIONS \ { "riscv_expand_arch", riscv_expand_arch }, \ { "riscv_expand_arch_from_cpu", riscv_expand_arch_from_cpu }, \ - { "riscv_default_mtune", riscv_default_mtune }, + { "riscv_default_mtune", riscv_default_mtune }, \ + { "riscv_multi_lib_check", riscv_multi_lib_check }, /* Support for a compile-time default CPU, et cetera. The rules are: --with-arch is ignored if -march or -mcpu is specified. -- cgit v1.1