diff options
author | Ian Lance Taylor <iant@golang.org> | 2020-07-11 12:43:49 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2020-07-11 12:43:49 -0700 |
commit | 4854d721be78358e59367982bdd94461b4be3c5a (patch) | |
tree | 8ead189e618f8ef1456c8b02c81de0cc1585d8a6 /libgcc | |
parent | 3cdc95b9f8d6c90c4a279783fd3da961c5afb22c (diff) | |
parent | e109f6e438b72ef3e403162971068d28d09b82f5 (diff) | |
download | gcc-4854d721be78358e59367982bdd94461b4be3c5a.zip gcc-4854d721be78358e59367982bdd94461b4be3c5a.tar.gz gcc-4854d721be78358e59367982bdd94461b4be3c5a.tar.bz2 |
Merge from trunk revision e109f6e438b72ef3e403162971068d28d09b82f5
Diffstat (limited to 'libgcc')
37 files changed, 1137 insertions, 1059 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 6340cfb..602c907 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,295 @@ +2020-07-09 Szabolcs Nagy <szabolcs.nagy@arm.com> + + PR target/96001 + * config/aarch64/lse.S: Add BTI marking and related definitions, + and add BTI c to function entries. + +2020-07-09 Szabolcs Nagy <szabolcs.nagy@arm.com> + + * config/aarch64/lse.S: Add stack note. + +2020-07-02 Martin Liska <mliska@suse.cz> + + PR gcov-profile/95348 + * libgcov-driver.c (merge_one_data): Merge only profiles + that are not of non-zero type. + (write_one_data): Write counters only if there's one non-zero + value. + * libgcov-util.c (tag_function): Change signature from unsigned + to int. + (tag_blocks): Likewise. + (tag_arcs): Likewise. + (tag_counters): Likewise. + (tag_summary): Likewise. + (tag_lines): Read only if COUNTERS is non-zero. + (read_gcda_file): Handle negative length for COUNTERS type. + +2020-06-25 Martin Liska <mliska@suse.cz> + + * libgcov-driver.c (merge_summary): Remove function as its name + is misleading and doing something different. + (dump_one_gcov): Add ATTRIBUTE_UNUSED for 2 args. Take read summary + in gcov-tool. + * libgcov-util.c (curr_object_summary): Remove. + (read_gcda_file): Remove unused curr_object_summary. + (gcov_merge): Merge summaries. + * libgcov.h: Add summary argument for gcov_info struct. + +2020-06-24 H.J. Lu <hjl.tools@gmail.com> + + PR target/95259 + * config/i386/cpuinfo.c: Don't include "cpuinfo.h". Include + "common/config/i386/i386-cpuinfo.h" and + "common/config/i386/cpuinfo.h". + (__cpu_features2): Changed to array. + (get_amd_cpu): Removed. + (get_intel_cpu): Likewise. + (get_available_features): Likewise. + (__cpu_indicator_init): Call cpu_indicator_init. + * config/i386/cpuinfo.h: Removed. + +2020-06-23 David Edelsohn <dje.gcc@gmail.com> + + * Makefile.in: Remove uses of empty.mk. Use -include. + * config/avr/t-avr: Use -include. + * empty.mk: Delete. + +2020-06-21 David Edelsohn <dje.gcc@gmail.com> + + * config.host (extra_parts): Add crtcxa_64 and crtdbase_64. + * config/rs6000/t-aix-cxa: Explicitly compile 32 bit with -maix32 + and 64 bit with -maix64. + * config/rs6000/t-slibgcc-aix: Remove extra @multilib_dir@ level. + Build and install AIX-style FAT libraries. + +2020-06-17 Samuel Thibault <samuel.thibault@gnu.org> + + * config.host (md_unwind_header) <i[34567]86-*-gnu*>: Set to + 'i386/gnu-unwind.h' + * config/i386/gnu-unwind.h: New file. + +2020-06-17 Martin Liska <mliska@suse.cz> + + * libgcov-util.c (read_gcda_finalize): Remove const operator. + (merge_wrapper): Add both counts and use them properly. + (topn_to_memory_representation): New function. + (gcov_merge): Covert on disk representation to in memory + representation. + * libgcov.h: Remove const operator. + +2020-06-15 Max Filippov <jcmvbkbc@gmail.com> + + * configure: Regenerate. + * configure.ac: Use AC_COMPILE_IFELSE instead of manual + preprocessor invocation to check for __XTENSA_CALL0_ABI__. + +2020-06-09 Martin Liska <mliska@suse.cz> + + PR gcov-profile/95494 + * libgcov-driver.c (write_top_counters): Cast first to + intptr_t as sizeof(*) != sizeof(gcov_type). + * libgcov.h (gcov_counter_set_if_null): Remove. + (gcov_topn_add_value): Cast first to intptr_t and update + linked list directly. + +2020-06-09 Max Filippov <jcmvbkbc@gmail.com> + + * config/xtensa/unwind-dw2-xtensa.c (uw_install_context): Merge + with uw_install_context_1. + +2020-06-04 Andreas Schwab <schwab@suse.de> + + PR target/59230 + PR libfortran/59227 + * config/ia64/t-softfp-compat (softfp_file_list): Filter out + soft-fp/divtf3.c. + (LIB2ADD): Add config/ia64/divtf3.c. + * config/ia64/divtf3.c: New file. + +2020-06-03 Martin Liska <mliska@suse.cz> + + PR gcov-profile/95480 + * libgcov-profiler.c (GCOV_SUPPORTS_ATOMIC): Move to... + * libgcov.h (GCOV_SUPPORTS_ATOMIC): ...here. + (gcov_counter_add): Use GCOV_SUPPORTS_ATOMIC guard. + (gcov_counter_set_if_null): Likewise. + +2020-06-02 Jim Wilson <jimw@sifive.com> + + * config/riscv/div.S (__divdi3): For negative arguments, change bgez + to bgtz. + +2020-06-02 Martin Liska <mliska@suse.cz> + + * libgcov.h (gcov_topn_add_value): Use xcalloc instead + of xmalloc. + +2020-06-02 Martin Liska <mliska@suse.cz> + + * libgcov-driver.c (prune_topn_counter): Remove. + (prune_counters): Likewise. + (merge_one_data): Special case TOP N counters + as they have variable length. + (write_top_counters): New. + (write_one_data): Special case TOP N. + (dump_one_gcov): Do not prune TOP N counters. + * libgcov-merge.c (merge_topn_values_set): Remove. + (__gcov_merge_topn): Use gcov_topn_add_value. + * libgcov-profiler.c (__gcov_topn_values_profiler_body): + Likewise here. + * libgcov.h (gcov_counter_add): New. + (gcov_counter_set_if_null): Likewise. + (gcov_topn_add_value): New. + +2020-06-01 Uroš Bizjak <ubizjak@gmail.com> + + * config/i386/sfp-exceptions.c (struct fenv): + Add __attribute__ ((gcc_struct)). + +2020-05-29 H.J. Lu <hjl.tools@gmail.com> + + PR bootstrap/95413 + * configure: Regenerated. + +2020-05-28 Dong JianQiang <dongjianqiang2@huawei.com> + + PR gcov-profile/95332 + * libgcov-util.c (read_gcda_file): Call gcov_magic. + * libgcov.h (gcov_magic): Disable GCC poison. + +2020-05-21 H.J. Lu <hongjiu.lu@intel.com> + + PR target/95212 + * config/i386/cpuinfo.h (processor_features): Move + FEATURE_AVX512VP2INTERSECT after FEATURE_AVX512BF16. + +2020-05-20 H.J. Lu <hongjiu.lu@intel.com> + + PR target/91695 + * config/i386/cpuinfo.c (get_available_features): Fix VPCLMULQDQ + check. + +2020-05-19 H.J. Lu <hongjiu.lu@intel.com> + + PR target/95212 + PR target/95220 + * config/i386/cpuinfo.c (get_available_features): Fix + FEATURE_GFNI check. Also check FEATURE_AVX512VP2INTERSECT. + * config/i386/cpuinfo.h (processor_features): Add + FEATURE_AVX512VP2INTERSECT. + +2020-05-15 H.J. Lu <hongjiu.lu@intel.com> + + PR bootstrap/95147 + * configure: Regenerated. + +2020-05-14 H.J. Lu <hongjiu.lu@intel.com> + + * configure: Regenerated. + +2020-05-09 Hans-Peter Nilsson <hp@axis.com> + + * config.host: Remove support for crisv32-*-* and cris*-*-linux. + * config/cris/libgcc-glibc.ver, config/cris/t-linux: Remove. + +2020-05-06 Uroš Bizjak <ubizjak@gmail.com> + + * config/i386/sfp-exceptions.c (__math_force_eval): Remove. + (__math_force_eval_div): New define. + (__sfp_handle_exceptions): Use __math_force_eval_div to use + generic division to generate INVALID, DIVZERO and INEXACT + exceptions. + +2020-05-06 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/aarch64/lse-init.c (init_have_lse_atomics): Use __getauxval + instead of getauxval. + (AT_HWCAP): Define. + (HWCAP_ATOMICS): Define. + Guard detection on __gnu_linux__. + +2020-05-05 Michael Meissner <meissner@linux.ibm.com> + + * config.host: Delete changes meant for a private branch. + * config/rs6000/t-float128: Likewise. + * configure.ac: Likewise. + * configure: Likewise. + +2020-05-05 Martin Liska <mliska@suse.cz> + + PR gcov-profile/93623 + * Makefile.in: Remove __gcov_flush. + * gcov.h (__gcov_flush): Remove. + * libgcov-interface.c (__gcov_flush): Remove. + (init_mx): Use renamed mutex. + (__gcov_lock): Likewise. + (__gcov_unlock): Likewise. + (__gcov_fork): Likewise. + (__gcov_flush): Remove. + +2020-05-05 Martin Liska <mliska@suse.cz> + + PR gcov-profile/93623 + * libgcov-interface.c (__gcov_fork): Do not flush + and reset only in child process. + (__gcov_execl): Dump counters only and reset them + only if exec* fails. + (__gcov_execlp): Likewise. + (__gcov_execle): Likewise. + (__gcov_execv): Likewise. + (__gcov_execvp): Likewise. + (__gcov_execve): Likewise. + +2020-05-05 Martin Liska <mliska@suse.cz> + + PR gcov-profile/93623 + * Makefile.in: Add _gcov_lock_unlock to LIBGCOV_INTERFACE. + * libgcov-interface.c (ALIAS_void_fn): Remove. + (__gcov_lock): New. + (__gcov_unlock): New. + (__gcov_flush): Use __gcov_lock and __gcov_unlock. + (__gcov_reset): Likewise. + (__gcov_dump): Likewise. + * libgcov.h (__gcov_lock): New declaration. + (__gcov_unlock): Likewise. + +2020-05-01 Uroš Bizjak <ubizjak@gmail.com> + + * config/i386/sfp-exceptions.c (__math_force_eval): New define. + (__sfp_handle_exceptions): Use __math_force_eval to evaluate + generic division to generate INVALID and DIVZERO exceptions. + +2020-04-27 Sebastian Huber <sebastian.huber@embedded-brains.de> + + * config/rs6000/crtresfpr.S: Use .machine ppc. + * config/rs6000/crtresxfpr.S: Likewise. + * config/rs6000/crtsavfpr.S: Likewise. + +2020-04-21 Szabolcs Nagy <szabolcs.nagy@arm.com> + + PR target/94514 + * config/aarch64/aarch64-unwind.h (aarch64_frob_update_context): + Update context->flags accroding to the frame state. + +2020-04-19 Uroš Bizjak <ubizjak@gmail.com> + + * config/i386/sfp-exceptions.c (__sfp_handle_exceptions) [__SSE_MATH__]: + Remove unneeded assignments to volatile memory. + +2020-04-15 Jakub Jelinek <jakub@redhat.com> + + PR target/93053 + * configure.ac (LIBGCC_CHECK_AS_LSE): Add HAVE_AS_LSE checking. + * config/aarch64/lse.S: Include auto-target.h, if HAVE_AS_LSE + is not defined, use just .arch armv8-a. + (B, M, N, OPN): Define. + (COMMENT): New .macro. + (CAS, CASP, SWP, LDOP): Use .inst directive if HAVE_AS_LSE is not + defined. Otherwise, move the operands right after the glue? and + comment out operands where the macros are used. + * configure: Regenerated. + * config.in: Regenerated. + 2020-04-07 Ian Lance Taylor <iant@golang.org> PR libgcc/94513 diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in index 851e765..d6075d3 100644 --- a/libgcc/Makefile.in +++ b/libgcc/Makefile.in @@ -373,7 +373,7 @@ gthr-default.h: $(srcdir)/$(thread_header) -$(LN_S) $< $@ tmake_file = @tmake_file@ -include $(srcdir)/empty.mk $(tmake_file) +-include $(tmake_file) # Collect target defines and headers from config.host. libgcc_tm_defines = @tm_defines@ @@ -393,7 +393,7 @@ ifeq ($(SHLIB_LINK),) endif ifeq ($(enable_shared),yes) - iterator = $(srcdir)/empty.mk $(patsubst %,$(srcdir)/shared-object.mk,$(iter-items)) + iterator = $(patsubst %,$(srcdir)/shared-object.mk,$(iter-items)) install-shared = install-shared @@ -425,7 +425,7 @@ gen-hide-list = echo > $@ endif ifneq ($(enable_shared),yes) -iterator = $(srcdir)/empty.mk $(patsubst %,$(srcdir)/static-object.mk,$(iter-items)) +iterator = $(patsubst %,$(srcdir)/static-object.mk,$(iter-items)) endif LIB2ADD += enable-execute-stack.c @@ -522,7 +522,7 @@ iter-items := $(sifuncs) $(difuncs) $(tifuncs) iter-labels := $(sifuncs) $(difuncs) $(difuncs) iter-sizes := $(patsubst %,4,$(sifuncs) $(difuncs)) $(patsubst %,8,$(tifuncs)) -include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/siditi-object.mk,$(iter-items)) +-include $(patsubst %,$(srcdir)/siditi-object.mk,$(iter-items)) libgcc-objects += $(patsubst %,%$(objext),$(sifuncs) $(difuncs) $(tifuncs)) ifeq ($(enable_shared),yes) @@ -805,7 +805,7 @@ iter-items := $(fixed-funcs) iter-labels := $(fixed-labels) iter-from := $(fixed-modes) iter-to := $(fixed-modes) -include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/fixed-obj.mk,$(iter-items)) +-include $(patsubst %,$(srcdir)/fixed-obj.mk,$(iter-items)) # Add arithmetic functions to list of objects to be built libgcc-objects += $(patsubst %,%$(objext),$(filter-out $(LIB2FUNCS_EXCLUDE),$(fixed-funcs))) @@ -824,7 +824,7 @@ iter-items := $(fixed-conv-funcs) iter-labels := $(fixed-conv-labels) iter-from := $(fixed-conv-from) iter-to := $(fixed-conv-to) -include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/fixed-obj.mk,$(iter-items)) +-include $(patsubst %,$(srcdir)/fixed-obj.mk,$(iter-items)) # Add conversion functions to list of objects to be built libgcc-objects += $(patsubst %,%$(objext),$(filter-out $(LIB2FUNCS_EXCLUDE),$(fixed-conv-funcs))) @@ -844,7 +844,7 @@ libgcc-objects += $(addsuffix $(objext),$(basename $(notdir $(LIB2ADD_ST)))) c_flags := iter-items := $(LIB2ADD) $(LIB2ADD_ST) -include $(iterator) +-include $(iterator) ifeq ($(enable_shared),yes) libgcc-s-objects += $(addsuffix _s$(objext),$(basename $(notdir $(LIB2ADD)))) @@ -862,7 +862,7 @@ libgcc-eh-objects += $(addsuffix $(objext),$(basename $(notdir $(LIB2ADDEHSTATIC libgcc-s-objects += $(addsuffix _s$(objext),$(basename $(notdir $(LIB2ADDEHSHARED)))) iter-items := $(sort $(LIB2ADDEHSTATIC) $(LIB2ADDEHSHARED)) -include $(iterator) +-include $(iterator) else # Not shared. LIB2ADDEH are added to libgcc.a. @@ -870,7 +870,7 @@ else libgcc-objects += $(addsuffix $(objext),$(basename $(notdir $(LIB2ADDEH)))) iter-items := $(LIB2ADDEH) -include $(iterator) +-include $(iterator) endif @@ -886,7 +886,7 @@ libunwind-s-objects += $(addsuffix _s$(objext),$(basename $(notdir $(LIBUNWIND)) endif iter-items := $(LIBUNWIND) -include $(iterator) +-include $(iterator) # Build libgcov components. @@ -904,9 +904,10 @@ LIBGCOV_PROFILER = _gcov_interval_profiler \ _gcov_ior_profiler_atomic \ _gcov_indirect_call_profiler_v4 \ _gcov_time_profiler -LIBGCOV_INTERFACE = _gcov_dump _gcov_flush _gcov_fork \ +LIBGCOV_INTERFACE = _gcov_dump _gcov_fork \ _gcov_execl _gcov_execlp \ - _gcov_execle _gcov_execv _gcov_execvp _gcov_execve _gcov_reset + _gcov_execle _gcov_execv _gcov_execvp _gcov_execve _gcov_reset \ + _gcov_lock_unlock LIBGCOV_DRIVER = _gcov libgcov-merge-objects = $(patsubst %,%$(objext),$(LIBGCOV_MERGE)) @@ -1202,4 +1203,4 @@ install-strip: install # configure. .NOEXPORT: -include $(srcdir)/empty.mk $(wildcard *.dep) +-include $(wildcard *.dep) diff --git a/libgcc/config.host b/libgcc/config.host index 1ff4159..7a3e29d 100644 --- a/libgcc/config.host +++ b/libgcc/config.host @@ -112,9 +112,6 @@ bpf-*-*) ;; cr16-*-*) ;; -crisv32-*-*) - cpu_type=cris - ;; csky*-*-*) cpu_type=csky ;; @@ -577,15 +574,9 @@ cr16-*-elf) tmake_file="${tmake_file} cr16/t-cr16 cr16/t-crtlibid t-fdpbit" extra_parts="$extra_parts crti.o crtn.o crtlibid.o" ;; -crisv32-*-elf) - tmake_file="$tmake_file cris/t-cris t-softfp-sfdf t-softfp" - ;; cris-*-elf) tmake_file="$tmake_file cris/t-cris t-softfp-sfdf t-softfp cris/t-elfmulti" ;; -cris-*-linux* | crisv32-*-linux*) - tmake_file="$tmake_file cris/t-cris t-softfp-sfdf t-softfp cris/t-linux" - ;; csky-*-elf*) tmake_file="csky/t-csky t-fdpbit" extra_parts="$extra_parts crti.o crtn.o" @@ -743,10 +734,16 @@ i[34567]86-*-linux*) tm_file="${tm_file} i386/elf-lib.h" md_unwind_header=i386/linux-unwind.h ;; -i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-gnu* | i[34567]86-*-kopensolaris*-gnu) +i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-kopensolaris*-gnu) + extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o" + tmake_file="${tmake_file} i386/t-crtpc t-crtfm i386/t-crtstuff t-dfprules" + tm_file="${tm_file} i386/elf-lib.h" + ;; +i[34567]86-*-gnu*) extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o" tmake_file="${tmake_file} i386/t-crtpc t-crtfm i386/t-crtstuff t-dfprules" tm_file="${tm_file} i386/elf-lib.h" + md_unwind_header=i386/gnu-unwind.h ;; x86_64-*-linux*) extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o" @@ -1276,7 +1273,7 @@ rs6000-ibm-aix5.1.* | powerpc-ibm-aix5.1.*) rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*) md_unwind_header=rs6000/aix-unwind.h tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-slibgcc-aix rs6000/t-ibm-ldouble rs6000/t-aix-cxa" - extra_parts="crtcxa.o crtcxa_s.o crtdbase.o" + extra_parts="crtcxa.o crtcxa_s.o crtdbase.o crtcxa_64.o crtcxa_64_s.o crtdbase_64.o" ;; rl78-*-elf) tmake_file="$tm_file t-fdpbit rl78/t-rl78" diff --git a/libgcc/config.in b/libgcc/config.in index 59a3d8d..5be5321 100644 --- a/libgcc/config.in +++ b/libgcc/config.in @@ -10,6 +10,9 @@ */ #undef HAVE_AS_CFI_SECTIONS +/* Define to 1 if the assembler supports LSE. */ +#undef HAVE_AS_LSE + /* Define to 1 if the target assembler supports thread-local storage. */ #undef HAVE_CC_TLS diff --git a/libgcc/config/aarch64/aarch64-unwind.h b/libgcc/config/aarch64/aarch64-unwind.h index 4c8790b..ed84a96 100644 --- a/libgcc/config/aarch64/aarch64-unwind.h +++ b/libgcc/config/aarch64/aarch64-unwind.h @@ -104,6 +104,8 @@ aarch64_frob_update_context (struct _Unwind_Context *context, if (fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset & 0x1) /* The flag is used for re-authenticating EH handler's address. */ context->flags |= RA_SIGNED_BIT; + else + context->flags &= ~RA_SIGNED_BIT; return; } diff --git a/libgcc/config/aarch64/lse-init.c b/libgcc/config/aarch64/lse-init.c index 74acef2..00e9ab8 100644 --- a/libgcc/config/aarch64/lse-init.c +++ b/libgcc/config/aarch64/lse-init.c @@ -29,19 +29,20 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see _Bool __aarch64_have_lse_atomics __attribute__((visibility("hidden"), nocommon)); -/* Disable initialization of __aarch64_have_lse_atomics during bootstrap. */ -#if !defined(inhibit_libc) && defined(HAVE_SYS_AUXV_H) -# include <sys/auxv.h> +/* Gate availability of __getauxval on glibc. All AArch64-supporting glibc + versions support it. */ +#ifdef __gnu_linux__ -/* Disable initialization if the system headers are too old. */ -# if defined(AT_HWCAP) && defined(HWCAP_ATOMICS) +# define AT_HWCAP 16 +# define HWCAP_ATOMICS (1 << 8) + +unsigned long int __getauxval (unsigned long int); static void __attribute__((constructor)) init_have_lse_atomics (void) { - unsigned long hwcap = getauxval (AT_HWCAP); + unsigned long hwcap = __getauxval (AT_HWCAP); __aarch64_have_lse_atomics = (hwcap & HWCAP_ATOMICS) != 0; } -# endif /* HWCAP */ -#endif /* inhibit_libc */ +#endif /* __gnu_linux__ */ diff --git a/libgcc/config/aarch64/lse.S b/libgcc/config/aarch64/lse.S index ca6495f..64691c6 100644 --- a/libgcc/config/aarch64/lse.S +++ b/libgcc/config/aarch64/lse.S @@ -48,8 +48,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see * separately to minimize code size. */ +#include "auto-target.h" + /* Tell the assembler to accept LSE instructions. */ +#ifdef HAVE_AS_LSE .arch armv8-a+lse +#else + .arch armv8-a +#endif /* Declare the symbol gating the LSE implementations. */ .hidden __aarch64_have_lse_atomics @@ -58,12 +64,19 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #if SIZE == 1 # define S b # define UXT uxtb +# define B 0x00000000 #elif SIZE == 2 # define S h # define UXT uxth +# define B 0x40000000 #elif SIZE == 4 || SIZE == 8 || SIZE == 16 # define S # define UXT mov +# if SIZE == 4 +# define B 0x80000000 +# elif SIZE == 8 +# define B 0xc0000000 +# endif #else # error #endif @@ -72,18 +85,26 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see # define SUFF _relax # define A # define L +# define M 0x000000 +# define N 0x000000 #elif MODEL == 2 # define SUFF _acq # define A a # define L +# define M 0x400000 +# define N 0x800000 #elif MODEL == 3 # define SUFF _rel # define A # define L l +# define M 0x008000 +# define N 0x400000 #elif MODEL == 4 # define SUFF _acq_rel # define A a # define L l +# define M 0x408000 +# define N 0xc00000 #else # error #endif @@ -115,6 +136,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define tmp1 17 #define tmp2 15 +#define BTI_C hint 34 + /* Start and end a function. */ .macro STARTFN name .text @@ -124,6 +147,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see .type \name, %function .cfi_startproc \name: + BTI_C .endm .macro ENDFN name @@ -144,9 +168,13 @@ STARTFN NAME(cas) JUMP_IF_NOT_LSE 8f #if SIZE < 16 -#define CAS glue4(cas, A, L, S) +#ifdef HAVE_AS_LSE +# define CAS glue4(cas, A, L, S) s(0), s(1), [x2] +#else +# define CAS .inst 0x08a07c41 + B + M +#endif - CAS s(0), s(1), [x2] + CAS /* s(0), s(1), [x2] */ ret 8: UXT s(tmp0), s(0) @@ -160,9 +188,13 @@ STARTFN NAME(cas) #else #define LDXP glue3(ld, A, xp) #define STXP glue3(st, L, xp) -#define CASP glue3(casp, A, L) +#ifdef HAVE_AS_LSE +# define CASP glue3(casp, A, L) x0, x1, x2, x3, [x4] +#else +# define CASP .inst 0x48207c82 + M +#endif - CASP x0, x1, x2, x3, [x4] + CASP /* x0, x1, x2, x3, [x4] */ ret 8: mov x(tmp0), x0 @@ -181,12 +213,16 @@ ENDFN NAME(cas) #endif #ifdef L_swp -#define SWP glue4(swp, A, L, S) +#ifdef HAVE_AS_LSE +# define SWP glue4(swp, A, L, S) s(0), s(0), [x1] +#else +# define SWP .inst 0x38208020 + B + N +#endif STARTFN NAME(swp) JUMP_IF_NOT_LSE 8f - SWP s(0), s(0), [x1] + SWP /* s(0), s(0), [x1] */ ret 8: mov s(tmp0), s(0) @@ -204,24 +240,32 @@ ENDFN NAME(swp) #ifdef L_ldadd #define LDNM ldadd #define OP add +#define OPN 0x0000 #elif defined(L_ldclr) #define LDNM ldclr #define OP bic +#define OPN 0x1000 #elif defined(L_ldeor) #define LDNM ldeor #define OP eor +#define OPN 0x2000 #elif defined(L_ldset) #define LDNM ldset #define OP orr +#define OPN 0x3000 #else #error #endif -#define LDOP glue4(LDNM, A, L, S) +#ifdef HAVE_AS_LSE +# define LDOP glue4(LDNM, A, L, S) s(0), s(0), [x1] +#else +# define LDOP .inst 0x38200020 + OPN + B + N +#endif STARTFN NAME(LDNM) JUMP_IF_NOT_LSE 8f - LDOP s(0), s(0), [x1] + LDOP /* s(0), s(0), [x1] */ ret 8: mov s(tmp0), s(0) @@ -233,3 +277,30 @@ STARTFN NAME(LDNM) ENDFN NAME(LDNM) #endif + +/* GNU_PROPERTY_AARCH64_* macros from elf.h for use in asm code. */ +#define FEATURE_1_AND 0xc0000000 +#define FEATURE_1_BTI 1 +#define FEATURE_1_PAC 2 + +/* Add a NT_GNU_PROPERTY_TYPE_0 note. */ +#define GNU_PROPERTY(type, value) \ + .section .note.gnu.property, "a"; \ + .p2align 3; \ + .word 4; \ + .word 16; \ + .word 5; \ + .asciz "GNU"; \ + .word type; \ + .word 4; \ + .word value; \ + .word 0; + +#if defined(__linux__) || defined(__FreeBSD__) +.section .note.GNU-stack, "", %progbits + +/* Add GNU property note if built with branch protection. */ +# ifdef __ARM_FEATURE_BTI_DEFAULT +GNU_PROPERTY (FEATURE_1_AND, FEATURE_1_BTI) +# endif +#endif diff --git a/libgcc/config/avr/libf7/ChangeLog b/libgcc/config/avr/libf7/ChangeLog index 1ec4735..d24215e 100644 --- a/libgcc/config/avr/libf7/ChangeLog +++ b/libgcc/config/avr/libf7/ChangeLog @@ -1,3 +1,7 @@ +2020-06-23 David Edelsohn <dje.gcc@gmail.com> + + * t-libf7: Use -include. + 2020-01-08 Georg-Johann Lay <avr@gjlay.de> Implement 64-bit double functions. diff --git a/libgcc/config/avr/libf7/t-libf7 b/libgcc/config/avr/libf7/t-libf7 index 92a27eb..30aa280 100644 --- a/libgcc/config/avr/libf7/t-libf7 +++ b/libgcc/config/avr/libf7/t-libf7 @@ -125,7 +125,7 @@ f7_parts := $(F7_C_PARTS) iter-items := $(f7_parts) iter-labels := $(f7_parts) -include $(srcdir)/empty.mk $(patsubst %,$(libf7)/libf7-c-object.mk,$(iter-items)) +-include $(patsubst %,$(libf7)/libf7-c-object.mk,$(iter-items)) libgcc-objects += $(patsubst %,f7_c_%$(objext),$(F7_C_PARTS)) @@ -136,7 +136,7 @@ f7_parts := $(F7_ASM_PARTS) iter-items := $(f7_parts) iter-labels := $(f7_parts) -include $(srcdir)/empty.mk $(patsubst %,$(libf7)/libf7-asm-object.mk,$(iter-items)) +-include $(patsubst %,$(libf7)/libf7-asm-object.mk,$(iter-items)) libgcc-objects += $(patsubst %,f7_asm_%$(objext),$(F7_ASM_PARTS)) diff --git a/libgcc/config/avr/t-avr b/libgcc/config/avr/t-avr index e4f867b..ed84b3f 100644 --- a/libgcc/config/avr/t-avr +++ b/libgcc/config/avr/t-avr @@ -132,7 +132,7 @@ iter-labels := $(siintfuncs16) iter-sizes := $(patsubst %,2,$(siintfuncs16)) $(patsubst %,2,$(hiintfuncs16)) -include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/siditi-object.mk,$(iter-items)) +-include $(patsubst %,$(srcdir)/siditi-object.mk,$(iter-items)) libgcc-objects += $(patsubst %,%$(objext),$(hiintfuncs16)) ifeq ($(enable_shared),yes) @@ -167,7 +167,7 @@ iter-items := $(round_funcs) iter-labels := $(round_suffix) iter-flags := $(patsubst %,-DL_round,$(iter-items)) -include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items)) +-include $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items)) libgcc-objects += $(patsubst %,%$(objext),$(round_funcs)) @@ -181,7 +181,7 @@ iter-items := $(clrsb_funcs) iter-labels := $(clrsb_funcs) iter-flags := $(patsubst %,-DL_clrsb,$(iter-items)) -include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items)) +-include $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items)) libgcc-objects += $(patsubst %,%$(objext),$(clrsb_funcs)) @@ -195,7 +195,7 @@ iter-items := $(countls_funcs) iter-labels := $(countls_modes) iter-flags := $(patsubst %,-DL_countls,$(iter-items)) -include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items)) +-include $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items)) libgcc-objects += $(patsubst %,%$(objext),$(countls_funcs)) @@ -209,7 +209,7 @@ iter-items := $(countlsu_funcs) iter-labels := $(countlsu_modes) iter-flags := $(patsubst %,-DL_countlsu,$(iter-items)) -include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items)) +-include $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items)) libgcc-objects += $(patsubst %,%$(objext),$(countlsu_funcs)) diff --git a/libgcc/config/cris/libgcc-glibc.ver b/libgcc/config/cris/libgcc-glibc.ver deleted file mode 100644 index e35de83..0000000 --- a/libgcc/config/cris/libgcc-glibc.ver +++ /dev/null @@ -1,7 +0,0 @@ -GCC_4.3 { - __Mul - __Div - __Udiv - __Mod - __Umod -} diff --git a/libgcc/config/cris/t-linux b/libgcc/config/cris/t-linux deleted file mode 100644 index 8c7f4d4..0000000 --- a/libgcc/config/cris/t-linux +++ /dev/null @@ -1,2 +0,0 @@ -# Override t-linux default. -SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/cris/libgcc-glibc.ver diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c index 00322c5..7218952 100644 --- a/libgcc/config/i386/cpuinfo.c +++ b/libgcc/config/i386/cpuinfo.c @@ -26,7 +26,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "cpuid.h" #include "tsystem.h" #include "auto-target.h" -#include "cpuinfo.h" +#include "common/config/i386/i386-cpuinfo.h" +#include "common/config/i386/cpuinfo.h" #ifdef HAVE_INIT_PRIORITY #define CONSTRUCTOR_PRIORITY (101) @@ -39,384 +40,14 @@ int __cpu_indicator_init (void) struct __processor_model __cpu_model = { }; -#ifndef SHARED /* We want to move away from __cpu_model in libgcc_s.so.1 and the size of __cpu_model is part of ABI. So, new features that don't fit into __cpu_model.__cpu_features[0] go into extra variables - in libgcc.a only, preferrably hidden. */ -unsigned int __cpu_features2; -#endif - - -/* Get the specific type of AMD CPU. */ - -static void -get_amd_cpu (unsigned int family, unsigned int model) -{ - switch (family) - { - /* AMD Family 10h. */ - case 0x10: - __cpu_model.__cpu_type = AMDFAM10H; - switch (model) - { - case 0x2: - /* Barcelona. */ - __cpu_model.__cpu_subtype = AMDFAM10H_BARCELONA; - break; - case 0x4: - /* Shanghai. */ - __cpu_model.__cpu_subtype = AMDFAM10H_SHANGHAI; - break; - case 0x8: - /* Istanbul. */ - __cpu_model.__cpu_subtype = AMDFAM10H_ISTANBUL; - break; - default: - break; - } - break; - /* AMD Family 14h "btver1". */ - case 0x14: - __cpu_model.__cpu_type = AMD_BTVER1; - break; - /* AMD Family 15h "Bulldozer". */ - case 0x15: - __cpu_model.__cpu_type = AMDFAM15H; - - if (model == 0x2) - __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2; - /* Bulldozer version 1. */ - else if (model <= 0xf) - __cpu_model.__cpu_subtype = AMDFAM15H_BDVER1; - /* Bulldozer version 2 "Piledriver" */ - else if (model <= 0x2f) - __cpu_model.__cpu_subtype = AMDFAM15H_BDVER2; - /* Bulldozer version 3 "Steamroller" */ - else if (model <= 0x4f) - __cpu_model.__cpu_subtype = AMDFAM15H_BDVER3; - /* Bulldozer version 4 "Excavator" */ - else if (model <= 0x7f) - __cpu_model.__cpu_subtype = AMDFAM15H_BDVER4; - break; - /* AMD Family 16h "btver2" */ - case 0x16: - __cpu_model.__cpu_type = AMD_BTVER2; - break; - case 0x17: - __cpu_model.__cpu_type = AMDFAM17H; - /* AMD family 17h version 1. */ - if (model <= 0x1f) - __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER1; - if (model >= 0x30) - __cpu_model.__cpu_subtype = AMDFAM17H_ZNVER2; - break; - default: - break; - } -} - -/* Get the specific type of Intel CPU. */ - -static void -get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id) -{ - /* Parse family and model only if brand ID is 0. */ - if (brand_id == 0) - { - switch (family) - { - case 0x5: - /* Pentium. */ - break; - case 0x6: - switch (model) - { - case 0x1c: - case 0x26: - /* Bonnell. */ - __cpu_model.__cpu_type = INTEL_BONNELL; - break; - case 0x37: - case 0x4a: - case 0x4d: - case 0x5a: - case 0x5d: - /* Silvermont. */ - __cpu_model.__cpu_type = INTEL_SILVERMONT; - break; - case 0x5c: - case 0x5f: - /* Goldmont. */ - __cpu_model.__cpu_type = INTEL_GOLDMONT; - break; - case 0x7a: - /* Goldmont Plus. */ - __cpu_model.__cpu_type = INTEL_GOLDMONT_PLUS; - break; - case 0x57: - /* Knights Landing. */ - __cpu_model.__cpu_type = INTEL_KNL; - break; - case 0x85: - /* Knights Mill. */ - __cpu_model.__cpu_type = INTEL_KNM; - break; - case 0x1a: - case 0x1e: - case 0x1f: - case 0x2e: - /* Nehalem. */ - __cpu_model.__cpu_type = INTEL_COREI7; - __cpu_model.__cpu_subtype = INTEL_COREI7_NEHALEM; - break; - case 0x25: - case 0x2c: - case 0x2f: - /* Westmere. */ - __cpu_model.__cpu_type = INTEL_COREI7; - __cpu_model.__cpu_subtype = INTEL_COREI7_WESTMERE; - break; - case 0x2a: - case 0x2d: - /* Sandy Bridge. */ - __cpu_model.__cpu_type = INTEL_COREI7; - __cpu_model.__cpu_subtype = INTEL_COREI7_SANDYBRIDGE; - break; - case 0x3a: - case 0x3e: - /* Ivy Bridge. */ - __cpu_model.__cpu_type = INTEL_COREI7; - __cpu_model.__cpu_subtype = INTEL_COREI7_IVYBRIDGE; - break; - case 0x3c: - case 0x3f: - case 0x45: - case 0x46: - /* Haswell. */ - __cpu_model.__cpu_type = INTEL_COREI7; - __cpu_model.__cpu_subtype = INTEL_COREI7_HASWELL; - break; - case 0x3d: - case 0x47: - case 0x4f: - case 0x56: - /* Broadwell. */ - __cpu_model.__cpu_type = INTEL_COREI7; - __cpu_model.__cpu_subtype = INTEL_COREI7_BROADWELL; - break; - case 0x4e: - case 0x5e: - /* Skylake. */ - case 0x8e: - case 0x9e: - /* Kaby Lake. */ - __cpu_model.__cpu_type = INTEL_COREI7; - __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE; - break; - case 0x55: - { - unsigned int eax, ebx, ecx, edx; - __cpu_model.__cpu_type = INTEL_COREI7; - __cpuid_count (7, 0, eax, ebx, ecx, edx); - if (ecx & bit_AVX512VNNI) - /* Cascade Lake. */ - __cpu_model.__cpu_subtype = INTEL_COREI7_CASCADELAKE; - else - /* Skylake with AVX-512 support. */ - __cpu_model.__cpu_subtype = INTEL_COREI7_SKYLAKE_AVX512; - } - break; - case 0x66: - /* Cannon Lake. */ - __cpu_model.__cpu_type = INTEL_COREI7; - __cpu_model.__cpu_subtype = INTEL_COREI7_CANNONLAKE; - break; - case 0x17: - case 0x1d: - /* Penryn. */ - case 0x0f: - /* Merom. */ - __cpu_model.__cpu_type = INTEL_CORE2; - break; - default: - break; - } - break; - default: - /* We have no idea. */ - break; - } - } -} - -/* ECX and EDX are output of CPUID at level one. MAX_CPUID_LEVEL is - the max possible level of CPUID insn. */ -static void -get_available_features (unsigned int ecx, unsigned int edx, - int max_cpuid_level) -{ - unsigned int eax, ebx; - unsigned int ext_level; - - unsigned int features = 0; - unsigned int features2 = 0; - - /* Get XCR_XFEATURE_ENABLED_MASK register with xgetbv. */ -#define XCR_XFEATURE_ENABLED_MASK 0x0 -#define XSTATE_FP 0x1 -#define XSTATE_SSE 0x2 -#define XSTATE_YMM 0x4 -#define XSTATE_OPMASK 0x20 -#define XSTATE_ZMM 0x40 -#define XSTATE_HI_ZMM 0x80 - -#define XCR_AVX_ENABLED_MASK \ - (XSTATE_SSE | XSTATE_YMM) -#define XCR_AVX512F_ENABLED_MASK \ - (XSTATE_SSE | XSTATE_YMM | XSTATE_OPMASK | XSTATE_ZMM | XSTATE_HI_ZMM) - - /* Check if AVX and AVX512 are usable. */ - int avx_usable = 0; - int avx512_usable = 0; - if ((ecx & bit_OSXSAVE)) - { - /* Check if XMM, YMM, OPMASK, upper 256 bits of ZMM0-ZMM15 and - ZMM16-ZMM31 states are supported by OSXSAVE. */ - unsigned int xcrlow; - unsigned int xcrhigh; - asm (".byte 0x0f, 0x01, 0xd0" - : "=a" (xcrlow), "=d" (xcrhigh) - : "c" (XCR_XFEATURE_ENABLED_MASK)); - if ((xcrlow & XCR_AVX_ENABLED_MASK) == XCR_AVX_ENABLED_MASK) - { - avx_usable = 1; - avx512_usable = ((xcrlow & XCR_AVX512F_ENABLED_MASK) - == XCR_AVX512F_ENABLED_MASK); - } - } - -#define set_feature(f) \ - do \ - { \ - if (f < 32) \ - features |= (1U << (f & 31)); \ - else \ - features2 |= (1U << ((f - 32) & 31)); \ - } \ - while (0) - - if (edx & bit_CMOV) - set_feature (FEATURE_CMOV); - if (edx & bit_MMX) - set_feature (FEATURE_MMX); - if (edx & bit_SSE) - set_feature (FEATURE_SSE); - if (edx & bit_SSE2) - set_feature (FEATURE_SSE2); - if (ecx & bit_POPCNT) - set_feature (FEATURE_POPCNT); - if (ecx & bit_AES) - set_feature (FEATURE_AES); - if (ecx & bit_PCLMUL) - set_feature (FEATURE_PCLMUL); - if (ecx & bit_SSE3) - set_feature (FEATURE_SSE3); - if (ecx & bit_SSSE3) - set_feature (FEATURE_SSSE3); - if (ecx & bit_SSE4_1) - set_feature (FEATURE_SSE4_1); - if (ecx & bit_SSE4_2) - set_feature (FEATURE_SSE4_2); - if (avx_usable) - { - if (ecx & bit_AVX) - set_feature (FEATURE_AVX); - if (ecx & bit_FMA) - set_feature (FEATURE_FMA); - } - - /* Get Advanced Features at level 7 (eax = 7, ecx = 0/1). */ - if (max_cpuid_level >= 7) - { - __cpuid_count (7, 0, eax, ebx, ecx, edx); - if (ebx & bit_BMI) - set_feature (FEATURE_BMI); - if (avx_usable) - { - if (ebx & bit_AVX2) - set_feature (FEATURE_AVX2); - } - if (ebx & bit_BMI2) - set_feature (FEATURE_BMI2); - if (avx512_usable) - { - if (ebx & bit_AVX512F) - set_feature (FEATURE_AVX512F); - if (ebx & bit_AVX512VL) - set_feature (FEATURE_AVX512VL); - if (ebx & bit_AVX512BW) - set_feature (FEATURE_AVX512BW); - if (ebx & bit_AVX512DQ) - set_feature (FEATURE_AVX512DQ); - if (ebx & bit_AVX512CD) - set_feature (FEATURE_AVX512CD); - if (ebx & bit_AVX512PF) - set_feature (FEATURE_AVX512PF); - if (ebx & bit_AVX512ER) - set_feature (FEATURE_AVX512ER); - if (ebx & bit_AVX512IFMA) - set_feature (FEATURE_AVX512IFMA); - if (ecx & bit_AVX512VBMI) - set_feature (FEATURE_AVX512VBMI); - if (ecx & bit_AVX512VBMI2) - set_feature (FEATURE_AVX512VBMI2); - if (ecx & bit_GFNI) - set_feature (FEATURE_GFNI); - if (ecx & bit_VPCLMULQDQ) - set_feature (FEATURE_VPCLMULQDQ); - if (ecx & bit_AVX512VNNI) - set_feature (FEATURE_AVX512VNNI); - if (ecx & bit_AVX512BITALG) - set_feature (FEATURE_AVX512BITALG); - if (ecx & bit_AVX512VPOPCNTDQ) - set_feature (FEATURE_AVX512VPOPCNTDQ); - if (edx & bit_AVX5124VNNIW) - set_feature (FEATURE_AVX5124VNNIW); - if (edx & bit_AVX5124FMAPS) - set_feature (FEATURE_AVX5124FMAPS); + in libgcc.a only, preferably hidden. - __cpuid_count (7, 1, eax, ebx, ecx, edx); - if (eax & bit_AVX512BF16) - set_feature (FEATURE_AVX512BF16); - } - } - - /* Check cpuid level of extended features. */ - __cpuid (0x80000000, ext_level, ebx, ecx, edx); - - if (ext_level >= 0x80000001) - { - __cpuid (0x80000001, eax, ebx, ecx, edx); - - if (ecx & bit_SSE4a) - set_feature (FEATURE_SSE4_A); - if (avx_usable) - { - if (ecx & bit_FMA4) - set_feature (FEATURE_FMA4); - if (ecx & bit_XOP) - set_feature (FEATURE_XOP); - } - } - - __cpu_model.__cpu_features[0] = features; -#ifndef SHARED - __cpu_features2 = features2; -#else - (void) features2; -#endif -} + NB: Since older 386-builtins.c accesses __cpu_features2 as scalar or + smaller array, it can only access the first few elements. */ +unsigned int __cpu_features2[SIZE_OF_CPU_FEATURES]; /* A constructor function that is sets __cpu_model and __cpu_features with the right values. This needs to run only once. This constructor is @@ -427,85 +58,9 @@ get_available_features (unsigned int ecx, unsigned int edx, int __attribute__ ((constructor CONSTRUCTOR_PRIORITY)) __cpu_indicator_init (void) { - unsigned int eax, ebx, ecx, edx; - - int max_level; - unsigned int vendor; - unsigned int model, family, brand_id; - unsigned int extended_model, extended_family; - - /* This function needs to run just once. */ - if (__cpu_model.__cpu_vendor) - return 0; - - /* Assume cpuid insn present. Run in level 0 to get vendor id. */ - if (!__get_cpuid (0, &eax, &ebx, &ecx, &edx)) - { - __cpu_model.__cpu_vendor = VENDOR_OTHER; - return -1; - } - - vendor = ebx; - max_level = eax; - - if (max_level < 1) - { - __cpu_model.__cpu_vendor = VENDOR_OTHER; - return -1; - } - - if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx)) - { - __cpu_model.__cpu_vendor = VENDOR_OTHER; - return -1; - } - - model = (eax >> 4) & 0x0f; - family = (eax >> 8) & 0x0f; - brand_id = ebx & 0xff; - extended_model = (eax >> 12) & 0xf0; - extended_family = (eax >> 20) & 0xff; - - if (vendor == signature_INTEL_ebx) - { - /* Adjust model and family for Intel CPUS. */ - if (family == 0x0f) - { - family += extended_family; - model += extended_model; - } - else if (family == 0x06) - model += extended_model; - - /* Get CPU type. */ - get_intel_cpu (family, model, brand_id); - /* Find available features. */ - get_available_features (ecx, edx, max_level); - __cpu_model.__cpu_vendor = VENDOR_INTEL; - } - else if (vendor == signature_AMD_ebx) - { - /* Adjust model and family for AMD CPUS. */ - if (family == 0x0f) - { - family += extended_family; - model += extended_model; - } - - /* Get CPU type. */ - get_amd_cpu (family, model); - /* Find available features. */ - get_available_features (ecx, edx, max_level); - __cpu_model.__cpu_vendor = VENDOR_AMD; - } - else - __cpu_model.__cpu_vendor = VENDOR_OTHER; - - gcc_assert (__cpu_model.__cpu_vendor < VENDOR_MAX); - gcc_assert (__cpu_model.__cpu_type < CPU_TYPE_MAX); - gcc_assert (__cpu_model.__cpu_subtype < CPU_SUBTYPE_MAX); - - return 0; + struct __processor_model2 cpu_model2; + return cpu_indicator_init (&__cpu_model, &cpu_model2, + __cpu_features2); } #if defined SHARED && defined USE_ELF_SYMVER diff --git a/libgcc/config/i386/cpuinfo.h b/libgcc/config/i386/cpuinfo.h deleted file mode 100644 index 41c4a49..0000000 --- a/libgcc/config/i386/cpuinfo.h +++ /dev/null @@ -1,135 +0,0 @@ -/* Get CPU type and Features for x86 processors. - Copyright (C) 2012-2020 Free Software Foundation, Inc. - Contributed by Sriraman Tallam (tmsriram@google.com) - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -<http://www.gnu.org/licenses/>. */ - -/* Processor Vendor and Models. */ - -enum processor_vendor -{ - VENDOR_INTEL = 1, - VENDOR_AMD, - VENDOR_OTHER, - VENDOR_MAX -}; - -/* Any new types or subtypes have to be inserted at the end. */ - -enum processor_types -{ - INTEL_BONNELL = 1, - INTEL_CORE2, - INTEL_COREI7, - AMDFAM10H, - AMDFAM15H, - INTEL_SILVERMONT, - INTEL_KNL, - AMD_BTVER1, - AMD_BTVER2, - AMDFAM17H, - INTEL_KNM, - INTEL_GOLDMONT, - INTEL_GOLDMONT_PLUS, - INTEL_TREMONT, - CPU_TYPE_MAX -}; - -enum processor_subtypes -{ - INTEL_COREI7_NEHALEM = 1, - INTEL_COREI7_WESTMERE, - INTEL_COREI7_SANDYBRIDGE, - AMDFAM10H_BARCELONA, - AMDFAM10H_SHANGHAI, - AMDFAM10H_ISTANBUL, - AMDFAM15H_BDVER1, - AMDFAM15H_BDVER2, - AMDFAM15H_BDVER3, - AMDFAM15H_BDVER4, - AMDFAM17H_ZNVER1, - INTEL_COREI7_IVYBRIDGE, - INTEL_COREI7_HASWELL, - INTEL_COREI7_BROADWELL, - INTEL_COREI7_SKYLAKE, - INTEL_COREI7_SKYLAKE_AVX512, - INTEL_COREI7_CANNONLAKE, - INTEL_COREI7_ICELAKE_CLIENT, - INTEL_COREI7_ICELAKE_SERVER, - AMDFAM17H_ZNVER2, - INTEL_COREI7_CASCADELAKE, - INTEL_COREI7_TIGERLAKE, - INTEL_COREI7_COOPERLAKE, - CPU_SUBTYPE_MAX -}; - -/* ISA Features supported. New features have to be inserted at the end. */ - -enum processor_features -{ - FEATURE_CMOV = 0, - FEATURE_MMX, - FEATURE_POPCNT, - FEATURE_SSE, - FEATURE_SSE2, - FEATURE_SSE3, - FEATURE_SSSE3, - FEATURE_SSE4_1, - FEATURE_SSE4_2, - FEATURE_AVX, - FEATURE_AVX2, - FEATURE_SSE4_A, - FEATURE_FMA4, - FEATURE_XOP, - FEATURE_FMA, - FEATURE_AVX512F, - FEATURE_BMI, - FEATURE_BMI2, - FEATURE_AES, - FEATURE_PCLMUL, - FEATURE_AVX512VL, - FEATURE_AVX512BW, - FEATURE_AVX512DQ, - FEATURE_AVX512CD, - FEATURE_AVX512ER, - FEATURE_AVX512PF, - FEATURE_AVX512VBMI, - FEATURE_AVX512IFMA, - FEATURE_AVX5124VNNIW, - FEATURE_AVX5124FMAPS, - FEATURE_AVX512VPOPCNTDQ, - FEATURE_AVX512VBMI2, - FEATURE_GFNI, - FEATURE_VPCLMULQDQ, - FEATURE_AVX512VNNI, - FEATURE_AVX512BITALG, - FEATURE_AVX512BF16 -}; - -extern struct __processor_model -{ - unsigned int __cpu_vendor; - unsigned int __cpu_type; - unsigned int __cpu_subtype; - unsigned int __cpu_features[1]; -} __cpu_model; -extern unsigned int __cpu_features2; diff --git a/libgcc/config/i386/gnu-unwind.h b/libgcc/config/i386/gnu-unwind.h new file mode 100644 index 0000000..db47f0a --- /dev/null +++ b/libgcc/config/i386/gnu-unwind.h @@ -0,0 +1,107 @@ +/* DWARF2 EH unwinding support for GNU Hurd: x86. + Copyright (C) 2020 Free Software Foundation, Inc. + Contributed by Samuel Thibault <samuel.thibault@gnu.org> + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +<http://www.gnu.org/licenses/>. */ + +/* Do code reading to identify a signal frame, and set the frame + state data appropriately. See unwind-dw2.c for the structs. */ + +#ifndef inhibit_libc + +#include <signal.h> + +#define MD_FALLBACK_FRAME_STATE_FOR x86_gnu_fallback_frame_state + +static _Unwind_Reason_Code +x86_gnu_fallback_frame_state +(struct _Unwind_Context *context, _Unwind_FrameState *fs) +{ + struct handler_args { + int signo; + int sigcode; + struct sigcontext *scp; + } *handler_args; + struct sigcontext *scp; + unsigned long usp; + +/* + * i386 sigtramp frame we are looking for follows. + * (see glibc/sysdeps/mach/hurd/i386/trampoline.c assembly) + * + * rpc_wait_trampoline: + * 0: b8 e7 ff ff ff mov $-25,%eax mach_msg_trap + * 5: 9a 00 00 00 00 07 00 lcall $7,$0 + * 12: 89 01 movl %eax, (%ecx) + * 14: 89 dc movl %ebx, %esp switch to signal stack + * + * trampoline: + * 16: ff d2 call *%edx call the handler function + * RA HERE + * 18: 83 c4 0c addl $12, %esp pop its args + * 21: c3 ret return to sigreturn + * + * firewall: + * 22: f4 hlt + */ + + if (!( *(unsigned int *)(context->ra ) == 0xc30cc483 + && *(unsigned char *)(context->ra + 4) == 0xf4 + + && *(unsigned int *)(context->ra - 4) == 0xd2ffdc89 + && *(unsigned int *)(context->ra - 8) == 0x01890007 + && *(unsigned int *)(context->ra - 12) == 0x00000000 + && *(unsigned int *)(context->ra - 16) == 0x9affffff + && *(unsigned short *)(context->ra - 18) == 0xe7b8)) + return _URC_END_OF_STACK; + + handler_args = context->cfa; + scp = handler_args->scp; + usp = scp->sc_uesp; + + fs->regs.cfa_how = CFA_REG_OFFSET; + fs->regs.cfa_reg = 4; + fs->regs.cfa_offset = usp - (unsigned long) context->cfa; + + fs->regs.reg[0].how = REG_SAVED_OFFSET; + fs->regs.reg[0].loc.offset = (unsigned long)&scp->sc_eax - usp; + fs->regs.reg[1].how = REG_SAVED_OFFSET; + fs->regs.reg[1].loc.offset = (unsigned long)&scp->sc_ecx - usp; + fs->regs.reg[2].how = REG_SAVED_OFFSET; + fs->regs.reg[2].loc.offset = (unsigned long)&scp->sc_edx - usp; + fs->regs.reg[3].how = REG_SAVED_OFFSET; + fs->regs.reg[3].loc.offset = (unsigned long)&scp->sc_ebx - usp; + fs->regs.reg[5].how = REG_SAVED_OFFSET; + fs->regs.reg[5].loc.offset = (unsigned long)&scp->sc_ebp - usp; + fs->regs.reg[6].how = REG_SAVED_OFFSET; + fs->regs.reg[6].loc.offset = (unsigned long)&scp->sc_esi - usp; + fs->regs.reg[7].how = REG_SAVED_OFFSET; + fs->regs.reg[7].loc.offset = (unsigned long)&scp->sc_edi - usp; + fs->regs.reg[8].how = REG_SAVED_OFFSET; + fs->regs.reg[8].loc.offset = (unsigned long)&scp->sc_eip - usp; + fs->retaddr_column = 8; + fs->signal_frame = 1; + + return _URC_NO_REASON; +} + +#endif /* ifndef inhibit_libc */ diff --git a/libgcc/config/i386/sfp-exceptions.c b/libgcc/config/i386/sfp-exceptions.c index c994491..3aed0af 100644 --- a/libgcc/config/i386/sfp-exceptions.c +++ b/libgcc/config/i386/sfp-exceptions.c @@ -39,26 +39,28 @@ struct fenv unsigned int __data_offset; unsigned short int __data_selector; unsigned short int __unused5; -}; +} __attribute__ ((gcc_struct)); + +#ifdef __SSE_MATH__ +# define __math_force_eval_div(x, y) \ + do { asm ("" : "+x" (x)); asm volatile ("" : : "x" (x / y)); } while (0) +#else +# define __math_force_eval_div(x, y) \ + do { asm ("" : "+t" (x)); asm volatile ("" : : "f" (x / y)); } while (0) +#endif void __sfp_handle_exceptions (int _fex) { + struct fenv temp; + if (_fex & FP_EX_INVALID) { float f = 0.0f; -#ifdef __SSE_MATH__ - volatile float r __attribute__ ((unused)); - asm volatile ("%vdivss\t{%0, %d0|%d0, %0}" : "+x" (f)); - r = f; /* Needed to trigger exception. */ -#else - asm volatile ("fdiv\t{%y0, %0|%0, %y0}" : "+t" (f)); - /* No need for fwait, exception is triggered by emitted fstp. */ -#endif + __math_force_eval_div (f, f); } if (_fex & FP_EX_DENORM) { - struct fenv temp; asm volatile ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= FP_EX_DENORM; asm volatile ("fldenv\t%0" : : "m" (temp)); @@ -67,18 +69,10 @@ __sfp_handle_exceptions (int _fex) if (_fex & FP_EX_DIVZERO) { float f = 1.0f, g = 0.0f; -#ifdef __SSE_MATH__ - volatile float r __attribute__ ((unused)); - asm volatile ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g)); - r = f; /* Needed to trigger exception. */ -#else - asm volatile ("fdivs\t%1" : "+t" (f) : "m" (g)); - /* No need for fwait, exception is triggered by emitted fstp. */ -#endif + __math_force_eval_div (f, g); } if (_fex & FP_EX_OVERFLOW) { - struct fenv temp; asm volatile ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= FP_EX_OVERFLOW; asm volatile ("fldenv\t%0" : : "m" (temp)); @@ -86,7 +80,6 @@ __sfp_handle_exceptions (int _fex) } if (_fex & FP_EX_UNDERFLOW) { - struct fenv temp; asm volatile ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= FP_EX_UNDERFLOW; asm volatile ("fldenv\t%0" : : "m" (temp)); @@ -95,14 +88,7 @@ __sfp_handle_exceptions (int _fex) if (_fex & FP_EX_INEXACT) { float f = 1.0f, g = 3.0f; -#ifdef __SSE_MATH__ - volatile float r __attribute__ ((unused)); - asm volatile ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g)); - r = f; /* Needed to trigger exception. */ -#else - asm volatile ("fdivs\t%1" : "+t" (f) : "m" (g)); - /* No need for fwait, exception is triggered by emitted fstp. */ -#endif + __math_force_eval_div (f, g); } } #endif diff --git a/libgcc/config/ia64/divtf3.c b/libgcc/config/ia64/divtf3.c new file mode 100644 index 0000000..e1afa29 --- /dev/null +++ b/libgcc/config/ia64/divtf3.c @@ -0,0 +1,9 @@ +#ifdef SHARED +#define __divtf3 __divtf3_shared +#endif + +#include "soft-fp/divtf3.c" + +#ifdef SHARED +asm (".symver __divtf3_shared, __divtf3@@GCC_4.4.0"); +#endif diff --git a/libgcc/config/ia64/t-softfp-compat b/libgcc/config/ia64/t-softfp-compat index 00f45d5..38bcea7 100644 --- a/libgcc/config/ia64/t-softfp-compat +++ b/libgcc/config/ia64/t-softfp-compat @@ -5,3 +5,6 @@ libgcc1-tf-functions = __divxf3 _fixtfdi _fixunstfdi _floatditf LIB1ASMFUNCS := $(filter-out $(libgcc1-tf-functions), $(LIB1ASMFUNCS)) libgcc1-tf-compats = $(addsuffix .S, $(libgcc1-tf-functions)) LIB2ADD += $(addprefix $(srcdir)/config/ia64/, $(libgcc1-tf-compats)) +# Wrap divtf3.c to set the default symbol version +softfp_file_list := $(filter-out $(srcdir)/soft-fp/divtf3.c, $(softfp_file_list)) +LIB2ADD += $(srcdir)/config/ia64/divtf3.c diff --git a/libgcc/config/libbid/ChangeLog b/libgcc/config/libbid/ChangeLog index 0920863..a1a9f46 100644 --- a/libgcc/config/libbid/ChangeLog +++ b/libgcc/config/libbid/ChangeLog @@ -1,3 +1,9 @@ +2020-05-05 Martin Liska <mliska@suse.cz> + + PR libgcc/92565 + * bid_internal.h (handle_UF_128_rem): Remove unused variable. + (handle_UF_128): Likewise. + 2020-01-01 Jakub Jelinek <jakub@redhat.com> Update copyright years. diff --git a/libgcc/config/libbid/bid_internal.h b/libgcc/config/libbid/bid_internal.h index cef36a9..9baa098 100644 --- a/libgcc/config/libbid/bid_internal.h +++ b/libgcc/config/libbid/bid_internal.h @@ -1540,8 +1540,6 @@ handle_UF_128_rem (UINT128 * pres, UINT64 sgn, int expon, UINT128 CQ, __shr_128 (CQ, Qh, amount); } - expon = 0; - #ifndef IEEE_ROUND_NEAREST_TIES_AWAY #ifndef IEEE_ROUND_NEAREST if (!(*prounding_mode)) @@ -1676,8 +1674,6 @@ handle_UF_128 (UINT128 * pres, UINT64 sgn, int expon, UINT128 CQ, __shr_128 (CQ, Qh, amount); } - expon = 0; - #ifndef IEEE_ROUND_NEAREST_TIES_AWAY #ifndef IEEE_ROUND_NEAREST if (!(*prounding_mode)) diff --git a/libgcc/config/riscv/div.S b/libgcc/config/riscv/div.S index 151f8e2..1723432 100644 --- a/libgcc/config/riscv/div.S +++ b/libgcc/config/riscv/div.S @@ -107,10 +107,12 @@ FUNC_END (__umoddi3) /* Handle negative arguments to __divdi3. */ .L10: neg a0, a0 - bgez a1, .L12 /* Compute __udivdi3(-a0, a1), then negate the result. */ + /* Zero is handled as a negative so that the result will not be inverted. */ + bgtz a1, .L12 /* Compute __udivdi3(-a0, a1), then negate the result. */ + neg a1, a1 - j __udivdi3 /* Compute __udivdi3(-a0, -a1). */ -.L11: /* Compute __udivdi3(a0, -a1), then negate the result. */ + j __udivdi3 /* Compute __udivdi3(-a0, -a1). */ +.L11: /* Compute __udivdi3(a0, -a1), then negate the result. */ neg a1, a1 .L12: move t0, ra diff --git a/libgcc/config/rs6000/crtresfpr.S b/libgcc/config/rs6000/crtresfpr.S index 6c0d01b..99e6f08 100644 --- a/libgcc/config/rs6000/crtresfpr.S +++ b/libgcc/config/rs6000/crtresfpr.S @@ -27,6 +27,7 @@ /* Do any initializations needed for the eabi environment */ + .machine ppc .section ".text" #include "ppc-asm.h" diff --git a/libgcc/config/rs6000/crtresxfpr.S b/libgcc/config/rs6000/crtresxfpr.S index 9f01fa5..9931db2 100644 --- a/libgcc/config/rs6000/crtresxfpr.S +++ b/libgcc/config/rs6000/crtresxfpr.S @@ -27,6 +27,7 @@ /* Do any initializations needed for the eabi environment */ + .machine ppc .section ".text" #include "ppc-asm.h" diff --git a/libgcc/config/rs6000/crtsavfpr.S b/libgcc/config/rs6000/crtsavfpr.S index fa043dd..dd8743a 100644 --- a/libgcc/config/rs6000/crtsavfpr.S +++ b/libgcc/config/rs6000/crtsavfpr.S @@ -27,6 +27,7 @@ /* Do any initializations needed for the eabi environment */ + .machine ppc .section ".text" #include "ppc-asm.h" diff --git a/libgcc/config/rs6000/t-aix-cxa b/libgcc/config/rs6000/t-aix-cxa index d7e6638..0e1bccb 100644 --- a/libgcc/config/rs6000/t-aix-cxa +++ b/libgcc/config/rs6000/t-aix-cxa @@ -8,10 +8,19 @@ LIB2ADD_ST += $(srcdir)/config/rs6000/aixinitfini.c SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-aix-cxa.ver crtdbase.o: $(srcdir)/config/rs6000/crtdbase.S - $(crt_compile) -c $< + $(crt_compile) -maix32 -c $< crtcxa.o: $(srcdir)/config/rs6000/crtcxa.c - $(crt_compile) -c $< + $(crt_compile) -maix32 -c $< crtcxa_s.o: $(srcdir)/config/rs6000/crtcxa.c - $(crt_compile) -DSHARED -c $< + $(crt_compile) -maix32 -DSHARED -c $< + +crtdbase_64.o: $(srcdir)/config/rs6000/crtdbase.S + $(crt_compile) -maix64 -c $< + +crtcxa_64.o: $(srcdir)/config/rs6000/crtcxa.c + $(crt_compile) -maix64 -c $< + +crtcxa_64_s.o: $(srcdir)/config/rs6000/crtcxa.c + $(crt_compile) -maix64 -DSHARED -c $< diff --git a/libgcc/config/rs6000/t-slibgcc-aix b/libgcc/config/rs6000/t-slibgcc-aix index 11db9ef..e5f8a02 100644 --- a/libgcc/config/rs6000/t-slibgcc-aix +++ b/libgcc/config/rs6000/t-slibgcc-aix @@ -37,48 +37,44 @@ SHLIB_SONAME = @shlib_base_name@.so.$(SHLIB_SOVERSION) SHLIB_LINK = \ if test svr4 != $(with_aix_soname) ; then \ $(CC) $(LIBGCC2_CFLAGS) -shared -Wl,-bnortl -nodefaultlibs \ - -Wl,-bE:@shlib_map_file@ -o @multilib_dir@/shr.o \ + -Wl,-bE:@shlib_map_file@ -o shr.o \ @multilib_flags@ @shlib_objs@ -lc \ `case @multilib_dir@ in \ *pthread*) echo -L$(TARGET_SYSTEM_ROOT)/usr/lib/threads -lpthreads -lc_r $(TARGET_SYSTEM_ROOT)/usr/lib/libc.a ;; \ *) echo -lc ;; esac` ; \ - rm -f @multilib_dir@/tmp-@shlib_base_name@.a ; \ - $(AR_CREATE_FOR_TARGET) @multilib_dir@/tmp-@shlib_base_name@.a \ - @multilib_dir@/shr.o ; \ - mv @multilib_dir@/tmp-@shlib_base_name@.a \ - @multilib_dir@/@shlib_base_name@.a ; \ - rm -f @multilib_dir@/shr.o ; \ + rm -f tmp-@shlib_base_name@.a ; \ + $(AR_CREATE_FOR_TARGET) tmp-@shlib_base_name@.a shr.o ; \ + mv tmp-@shlib_base_name@.a @shlib_base_name@.a ; \ + rm -f shr.o ; \ fi ; \ if test aix != $(with_aix_soname) ; then \ case @multilib_dir@ in *64*) shr='shr_64' ;; *) shr='shr' ;; esac ; \ $(CC) $(LIBGCC2_CFLAGS) -shared -Wl,-G -nodefaultlibs \ - -Wl,-bE:@shlib_map_file@ -o @multilib_dir@/$$shr.o \ + -Wl,-bE:@shlib_map_file@ -o $$shr.o \ @multilib_flags@ @shlib_objs@ -lc \ `case @multilib_dir@ in \ *pthread*) echo -L$(TARGET_SYSTEM_ROOT)/usr/lib/threads -lpthreads -lc_r $(TARGET_SYSTEM_ROOT)/usr/lib/libc.a ;; \ *) echo -lc ;; esac` ; \ - $(STRIP_FOR_TARGET) -X32_64 -e @multilib_dir@/$$shr.o ; \ + $(STRIP_FOR_TARGET) -X32_64 -e $$shr.o ; \ { echo "\#! $(SHLIB_SONAME)($$shr.o)" ; \ case @multilib_dir@ in *64*) echo '\# 64' ;; *) echo '\# 32' ;; esac ; \ cat @shlib_map_file@ ; \ - } > @multilib_dir@/$$shr.imp ; \ - rm -f @multilib_dir@/tmp-$(SHLIB_SONAME) ; \ - $(AR_CREATE_FOR_TARGET) @multilib_dir@/tmp-$(SHLIB_SONAME) \ - @multilib_dir@/$$shr.imp @multilib_dir@/$$shr.o ; \ - mv @multilib_dir@/tmp-$(SHLIB_SONAME) \ - @multilib_dir@/$(SHLIB_SONAME) ; \ - rm -f @multilib_dir@/@shlib_base_name@.so ; \ - $(LN_S) $(SHLIB_SONAME) @multilib_dir@/@shlib_base_name@.so ; \ - rm -f @multilib_dir@/$$shr.imp @multilib_dir@/$$shr.o ; \ + } > $$shr.imp ; \ + rm -f tmp-$(SHLIB_SONAME) ; \ + $(AR_CREATE_FOR_TARGET) tmp-$(SHLIB_SONAME) $$shr.imp $$shr.o ; \ + mv tmp-$(SHLIB_SONAME) $(SHLIB_SONAME) ; \ + rm -f @shlib_base_name@.so ; \ + $(LN_S) $(SHLIB_SONAME) @shlib_base_name@.so ; \ + rm -f $$shr.imp $$shr.o ; \ fi SHLIB_INSTALL = \ $(mkinstalldirs) $(DESTDIR)$(slibdir)@shlib_slibdir_qual@; \ if test svr4 != $(with_aix_soname) ; then \ - $(INSTALL_DATA) @multilib_dir@/@shlib_base_name@.a \ + $(INSTALL_DATA) @shlib_base_name@.a \ $(DESTDIR)$(slibdir)@shlib_slibdir_qual@/ ; \ fi ; \ if test aix != $(with_aix_soname) ; then \ - $(INSTALL_DATA) @multilib_dir@/$(SHLIB_SONAME) \ + $(INSTALL_DATA) $(SHLIB_SONAME) \ $(DESTDIR)$(slibdir)@shlib_slibdir_qual@/ ; \ rm -f $(DESTDIR)$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so ; \ $(LN_S) $(SHLIB_SONAME) \ @@ -91,3 +87,36 @@ SHLIB_NM_FLAGS = -Bpg -X32_64 # Either 32-bit and 64-bit objects in archives. AR_FLAGS_FOR_TARGET = -X32_64 + +# Build and install AIX-style FAT libraries +ifeq ($(MULTIBUILDTOP),) +BITS=$(shell if test -z "`ar -X64 t libgcc_s.a`" ; then \ + echo '64'; else echo '32'; fi) +all: all-multi +ifeq ($(enable_shared),yes) + ar -X$(BITS) x ../ppc$(BITS)/libgcc/libgcc_s.a shr.o + ar -X$(BITS) rc ./libgcc_s.a shr.o + rm -f shr.o + ar -X$(BITS) x ../pthread/ppc$(BITS)/libgcc/libgcc_s.a shr.o + ar -X$(BITS) rc ../pthread/libgcc/libgcc_s.a shr.o + rm -f shr.o +endif + ar -X$(BITS) rc libgcc.a \ + $(addprefix ../ppc$(BITS)/libgcc/,$(libgcc-objects)) + ar -X$(BITS) rc libgcc_eh.a \ + $(addprefix ../ppc$(BITS)/libgcc/,$(libgcc-eh-objects)) + ar -X$(BITS) rc ../pthread/libgcc/libgcc.a \ + $(addprefix ../pthread/ppc$(BITS)/libgcc/,$(libgcc-objects)) + ar -X$(BITS) rc ../pthread/libgcc/libgcc_eh.a \ + $(addprefix ../pthread/ppc$(BITS)/libgcc/,$(libgcc-eh-objects)) +ifeq ($(enable_gcov),yes) + ar -X$(BITS) rc libgcov.a \ + $(addprefix ../ppc$(BITS)/libgcc/,$(libgcov-objects)) + ar -X$(BITS) rc ../pthread/libgcc/libgcov.a \ + $(addprefix ../pthread/ppc$(BITS)/libgcc/,$(libgcov-objects)) +endif + $(MAKE) install-leaf DESTDIR=$(gcc_objdir) \ + slibdir= libsubdir= MULTIOSDIR=$(MULTIDIR) + cp ../pthread/libgcc/libgcc_s.a ../../gcc/pthread/ + cp ../pthread/libgcc/libgcc_eh.a ../../gcc/pthread/ +endif diff --git a/libgcc/config/xtensa/unwind-dw2-xtensa.c b/libgcc/config/xtensa/unwind-dw2-xtensa.c index 056182a..8a6a44a 100644 --- a/libgcc/config/xtensa/unwind-dw2-xtensa.c +++ b/libgcc/config/xtensa/unwind-dw2-xtensa.c @@ -481,37 +481,35 @@ uw_init_context_1 (struct _Unwind_Context *context, void *outer_cfa, /* Install TARGET into CURRENT so that we can return to it. This is a macro because __builtin_eh_return must be invoked in the context of - our caller. */ + our caller, and also because spilling registers of the caller before + the context installation may result in reload of wrong register values + after the context installation due to the change of the stack pointer + in the base save area. This spilling may be caused by an interrupt + handler on baremetal host. */ -#define uw_install_context(CURRENT, TARGET, FRAMES) \ +#define uw_install_context(CURRENT, TARGET, FRAMES) \ do \ { \ - long offset = uw_install_context_1 ((CURRENT), (TARGET)); \ void *handler = __builtin_frob_return_addr ((TARGET)->ra); \ - __builtin_eh_return (offset, handler); \ + long i; \ + \ + /* The eh_return insn assumes a window size of 8, so don't bother \ + copying the save areas for registers a8-a15 since they won't be \ + reloaded. */ \ + for (i = 0; i < 2; ++i) \ + { \ + _Unwind_Word *c = (CURRENT)->reg[i]; \ + _Unwind_Word *t = (TARGET)->reg[i]; \ + int j; \ + \ + if (t && c && t != c) \ + for (j = 0; j < 4; ++j) \ + *c++ = *t++; \ + } \ + __builtin_eh_return (0, handler); \ } \ while (0) -static long -uw_install_context_1 (struct _Unwind_Context *current, - struct _Unwind_Context *target) -{ - long i; - - /* The eh_return insn assumes a window size of 8, so don't bother copying - the save areas for registers a8-a15 since they won't be reloaded. */ - for (i = 0; i < 2; ++i) - { - void *c = current->reg[i]; - void *t = target->reg[i]; - - if (t && c && t != c) - memcpy (c, t, 4 * sizeof (_Unwind_Word)); - } - - return 0; -} - static inline _Unwind_Ptr uw_identify_context (struct _Unwind_Context *context) { diff --git a/libgcc/configure b/libgcc/configure index 093036a..284e4db 100755 --- a/libgcc/configure +++ b/libgcc/configure @@ -1353,7 +1353,7 @@ Optional Features: enable decimal float extension to C. Selecting 'bid' or 'dpd' choses which decimal floating point format to use - --enable-cet enable Intel CET in target libraries [default=no] + --enable-cet enable Intel CET in target libraries [default=auto] --enable-explicit-exception-frame-registration register exception tables explicitly at module start, for use e.g. for compatibility with @@ -4900,19 +4900,22 @@ if test "${enable_cet+set}" = set; then : esac else - enable_cet=no + enable_cet=auto fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CET support" >&5 $as_echo_n "checking for CET support... " >&6; } +# NB: Avoid nested save_CFLAGS and save_LDFLAGS. case "$host" in i[34567]86-*-linux* | x86_64-*-linux*) case "$enable_cet" in auto) # Check if target supports multi-byte NOPs # and if assembler supports CET insn. + cet_save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fcf-protection" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -4936,6 +4939,7 @@ else enable_cet=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$cet_save_CFLAGS" ;; yes) # Check if assembler supports CET. @@ -5326,19 +5330,17 @@ esac # This is after config.host so we can augment tmake_file. case ${host} in xtensa*-*) - cat > conftest.c <<EOF - #ifdef __XTENSA_CALL0_ABI__ - #error - #endif -EOF - if { ac_try='${CC-cc} -E -o conftest.i conftest.c 1>&5' - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 - (eval $ac_try) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then - tmake_file="${tmake_file} xtensa/t-windowed" - fi + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __XTENSA_CALL0_ABI__ + #error + #endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + tmake_file="${tmake_file} xtensa/t-windowed" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ;; esac @@ -5530,6 +5532,46 @@ $as_echo "#define HAVE_AS_AVX 1" >>confdefs.h ;; esac + + +case "${target}" in +aarch64*-*-*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the assembler supports LSE" >&5 +$as_echo_n "checking if the assembler supports LSE... " >&6; } +if ${libgcc_cv_as_lse+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + asm(".arch armv8-a+lse\n\tcas w0, w1, [x2]"); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + libgcc_cv_as_lse=yes +else + libgcc_cv_as_lse=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_as_lse" >&5 +$as_echo "$libgcc_cv_as_lse" >&6; } + if test x$libgcc_cv_as_lse = xyes; then + +$as_echo "#define HAVE_AS_LSE 1" >>confdefs.h + + fi + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for init priority support" >&5 $as_echo_n "checking for init priority support... " >&6; } if ${libgcc_cv_init_priority+:} false; then : diff --git a/libgcc/configure.ac b/libgcc/configure.ac index 85979da9..ef0d799 100644 --- a/libgcc/configure.ac +++ b/libgcc/configure.ac @@ -515,14 +515,12 @@ AC_SUBST(solaris_ld_v2_maps) # This is after config.host so we can augment tmake_file. case ${host} in xtensa*-*) - cat > conftest.c <<EOF - #ifdef __XTENSA_CALL0_ABI__ - #error - #endif -EOF - if AC_TRY_COMMAND(${CC-cc} -E -o conftest.i conftest.c 1>&AS_MESSAGE_LOG_FD); then - tmake_file="${tmake_file} xtensa/t-windowed" - fi + AC_COMPILE_IFELSE([AC_LANG_SOURCE( + [#ifdef __XTENSA_CALL0_ABI__ + #error + #endif + ])], + [tmake_file="${tmake_file} xtensa/t-windowed"]) ;; esac @@ -599,6 +597,25 @@ i[[34567]]86-*-* | x86_64-*-*) esac]) LIBGCC_CHECK_AS_AVX +dnl Check if as supports LSE instructions. +AC_DEFUN([LIBGCC_CHECK_AS_LSE], [ +case "${target}" in +aarch64*-*-*) + AC_CACHE_CHECK([if the assembler supports LSE], libgcc_cv_as_lse, [ + AC_TRY_COMPILE([], +changequote(,)dnl + asm(".arch armv8-a+lse\n\tcas w0, w1, [x2]"); +changequote([,])dnl + , + [libgcc_cv_as_lse=yes], [libgcc_cv_as_lse=no]) + ]) + if test x$libgcc_cv_as_lse = xyes; then + AC_DEFINE(HAVE_AS_LSE, 1, [Define to 1 if the assembler supports LSE.]) + fi + ;; +esac]) +LIBGCC_CHECK_AS_LSE + dnl Check if as supports RTM instructions. AC_CACHE_CHECK(for init priority support, libgcc_cv_init_priority, [ AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, diff --git a/libgcc/empty.mk b/libgcc/empty.mk deleted file mode 100644 index 7b1d97b..0000000 --- a/libgcc/empty.mk +++ /dev/null @@ -1,2 +0,0 @@ -# Empty. This file exists to suppress errors in the parent Makefile -# when a variable (e.g. LIB2ADD) is empty. diff --git a/libgcc/gcov.h b/libgcc/gcov.h index f158191..0e3eed3 100644 --- a/libgcc/gcov.h +++ b/libgcc/gcov.h @@ -33,9 +33,4 @@ extern void __gcov_reset (void); extern void __gcov_dump (void); -/* Write profile information to a file and reset counters to zero. - The function does operations under a mutex. */ - -extern void __gcov_flush (void); - #endif /* GCC_GCOV_H */ diff --git a/libgcc/libgcov-driver.c b/libgcc/libgcov-driver.c index fb32073..2590593 100644 --- a/libgcc/libgcov-driver.c +++ b/libgcc/libgcov-driver.c @@ -213,51 +213,6 @@ static struct gcov_fn_buffer *fn_buffer; /* Including system dependent components. */ #include "libgcov-driver-system.c" -/* Prune TOP N value COUNTERS. It's needed in order to preserve - reproducibility of builds. */ - -static void -prune_topn_counter (gcov_type *counters, gcov_type all) -{ - for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++) - if (counters[2 * i + 1] < all) - { - counters[2 * i] = 0; - counters[2 * i + 1] = 0; - } -} - -/* Prune counters so that they are ready to store or merge. */ - -static void -prune_counters (struct gcov_info *gi) -{ - for (unsigned i = 0; i < gi->n_functions; i++) - { - const struct gcov_fn_info *gfi = gi->functions[i]; - const struct gcov_ctr_info *ci = gfi->ctrs; - - for (unsigned j = 0; j < GCOV_COUNTERS; j++) - { - if (gi->merge[j] == NULL) - continue; - - if (gi->merge[j] == __gcov_merge_topn) - { - gcc_assert (!(ci->num % GCOV_TOPN_VALUES_COUNTERS)); - for (unsigned k = 0; k < (ci->num / GCOV_TOPN_VALUES_COUNTERS); - k++) - { - gcov_type *counters - = ci->values + (k * GCOV_TOPN_VALUES_COUNTERS); - prune_topn_counter (counters + 1, *counters); - } - } - ci++; - } - } -} - /* This function merges counters in GI_PTR to an existing gcda file. Return 0 on success. Return -1 on error. In this case, caller will goto read_fatal. */ @@ -346,16 +301,21 @@ merge_one_data (const char *filename, if (!merge) continue; - tag = gcov_read_unsigned (); - length = gcov_read_unsigned (); - if (tag != GCOV_TAG_FOR_COUNTER (t_ix) - || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num)) - goto read_mismatch; - (*merge) (ci_ptr->values, ci_ptr->num); - ci_ptr++; - } + tag = gcov_read_unsigned (); + int read_length = (int)gcov_read_unsigned (); + length = abs (read_length); + if (tag != GCOV_TAG_FOR_COUNTER (t_ix) + || (length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num) + && t_ix != GCOV_COUNTER_V_TOPN + && t_ix != GCOV_COUNTER_V_INDIR)) + goto read_mismatch; + /* Merging with all zero counters does not make sense. */ + if (read_length > 0) + (*merge) (ci_ptr->values, ci_ptr->num); + ci_ptr++; + } if ((error = gcov_is_error ())) - goto read_error; + goto read_error; } if (tag) @@ -374,6 +334,37 @@ read_error: return -1; } +/* Store all TOP N counters where each has a dynamic length. */ + +static void +write_top_counters (const struct gcov_ctr_info *ci_ptr, + unsigned t_ix, + gcov_unsigned_t n_counts) +{ + unsigned counters = n_counts / GCOV_TOPN_MEM_COUNTERS; + gcc_assert (n_counts % GCOV_TOPN_MEM_COUNTERS == 0); + unsigned pair_total = 0; + for (unsigned i = 0; i < counters; i++) + pair_total += ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i + 1]; + unsigned disk_size = GCOV_TOPN_DISK_COUNTERS * counters + 2 * pair_total; + gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), + GCOV_TAG_COUNTER_LENGTH (disk_size)); + + for (unsigned i = 0; i < counters; i++) + { + gcov_type pair_count = ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i + 1]; + gcov_write_counter (ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i]); + gcov_write_counter (pair_count); + gcov_type start = ci_ptr->values[GCOV_TOPN_MEM_COUNTERS * i + 2]; + for (struct gcov_kvp *node = (struct gcov_kvp *)(intptr_t)start; + node != NULL; node = node->next) + { + gcov_write_counter (node->value); + gcov_write_counter (node->count); + } + } +} + /* Write counters in GI_PTR and the summary in PRG to a gcda file. In the case of appending to an existing file, SUMMARY_POS will be non-zero. We will write the file starting from SUMMAY_POS. */ @@ -426,20 +417,40 @@ write_one_data (const struct gcov_info *gi_ptr, ci_ptr = gfi_ptr->ctrs; for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) { - gcov_unsigned_t n_counts; - gcov_type *c_ptr; + gcov_position_t n_counts; - if (!gi_ptr->merge[t_ix]) - continue; + if (!gi_ptr->merge[t_ix]) + continue; - n_counts = ci_ptr->num; - gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), - GCOV_TAG_COUNTER_LENGTH (n_counts)); - c_ptr = ci_ptr->values; - while (n_counts--) - gcov_write_counter (*c_ptr++); - ci_ptr++; - } + n_counts = ci_ptr->num; + + if (gi_ptr->merge[t_ix] == __gcov_merge_topn) + write_top_counters (ci_ptr, t_ix, n_counts); + else + { + /* Do not stream when all counters are zero. */ + int all_zeros = 1; + for (unsigned i = 0; i < n_counts; i++) + if (ci_ptr->values[i] != 0) + { + all_zeros = 0; + break; + } + + if (all_zeros) + gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), + GCOV_TAG_COUNTER_LENGTH (-n_counts)); + else + { + gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), + GCOV_TAG_COUNTER_LENGTH (n_counts)); + for (unsigned i = 0; i < n_counts; i++) + gcov_write_counter (ci_ptr->values[i]); + } + } + + ci_ptr++; + } if (buffered) fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS); } @@ -447,19 +458,6 @@ write_one_data (const struct gcov_info *gi_ptr, gcov_write_unsigned (0); } -/* Helper function for merging summary. */ - -static void -merge_summary (int run_counted, struct gcov_summary *summary, - gcov_type run_max) -{ - if (!run_counted) - { - summary->runs++; - summary->sum_max += run_max; - } -} - /* Dump the coverage counts for one gcov_info object. We merge with existing counts when possible, to avoid growing the .da files ad infinitum. We use this program's checksum to make sure we only accumulate whole program @@ -469,16 +467,14 @@ merge_summary (int run_counted, struct gcov_summary *summary, static void dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf, - unsigned run_counted, gcov_type run_max) + unsigned run_counted ATTRIBUTE_UNUSED, + gcov_type run_max ATTRIBUTE_UNUSED) { struct gcov_summary summary = {}; int error; gcov_unsigned_t tag; fn_buffer = 0; - /* Prune current counters before we merge them. */ - prune_counters (gi_ptr); - error = gcov_exit_open_gcda_file (gi_ptr, gf); if (error == -1) return; @@ -500,7 +496,15 @@ dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf, gcov_rewrite (); - merge_summary (run_counted, &summary, run_max); +#if !IN_GCOV_TOOL + if (!run_counted) + { + summary.runs++; + summary.sum_max += run_max; + } +#else + summary = gi_ptr->summary; +#endif write_one_data (gi_ptr, &summary); /* fall through */ diff --git a/libgcc/libgcov-interface.c b/libgcc/libgcov-interface.c index 048b902..3a8a5bf 100644 --- a/libgcc/libgcov-interface.c +++ b/libgcc/libgcov-interface.c @@ -28,10 +28,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #if defined(inhibit_libc) -#ifdef L_gcov_flush -void __gcov_flush (void) {} -#endif - #ifdef L_gcov_reset void __gcov_reset (void) {} #endif @@ -42,28 +38,19 @@ void __gcov_dump (void) {} #else -/* Some functions we want to bind in this dynamic object, but have an - overridable global alias. Unfortunately not all targets support - aliases, so we just have a forwarding function. That'll be tail - called, so the cost is a single jump instruction.*/ - -#define ALIAS_void_fn(src,dst) \ - void dst (void) \ - { src (); } - -extern __gthread_mutex_t __gcov_flush_mx ATTRIBUTE_HIDDEN; +extern __gthread_mutex_t __gcov_mx ATTRIBUTE_HIDDEN; -#ifdef L_gcov_flush +#ifdef L_gcov_lock_unlock #ifdef __GTHREAD_MUTEX_INIT -__gthread_mutex_t __gcov_flush_mx = __GTHREAD_MUTEX_INIT; +__gthread_mutex_t __gcov_mx = __GTHREAD_MUTEX_INIT; #define init_mx_once() #else -__gthread_mutex_t __gcov_flush_mx; +__gthread_mutex_t __gcov_mx; static void init_mx (void) { - __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx); + __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_mx); } static void @@ -74,23 +61,23 @@ init_mx_once (void) } #endif -/* Called before fork or exec - write out profile information gathered so - far and reset it to zero. This avoids duplication or loss of the - profile information gathered so far. */ +/* Lock critical section for __gcov_dump and __gcov_reset functions. */ void -__gcov_flush (void) +__gcov_lock (void) { init_mx_once (); - __gthread_mutex_lock (&__gcov_flush_mx); + __gthread_mutex_lock (&__gcov_mx); +} - __gcov_dump_int (); - __gcov_reset_int (); +/* Unlock critical section for __gcov_dump and __gcov_reset functions. */ - __gthread_mutex_unlock (&__gcov_flush_mx); +void +__gcov_unlock (void) +{ + __gthread_mutex_unlock (&__gcov_mx); } - -#endif /* L_gcov_flush */ +#endif #ifdef L_gcov_reset @@ -143,7 +130,17 @@ __gcov_reset_int (void) } } -ALIAS_void_fn (__gcov_reset_int, __gcov_reset); +/* Exported function __gcov_reset. */ + +void +__gcov_reset (void) +{ + __gcov_lock (); + + __gcov_reset_int (); + + __gcov_unlock (); +} #endif /* L_gcov_reset */ @@ -163,22 +160,35 @@ __gcov_dump_int (void) __gcov_dump_one (root); } -ALIAS_void_fn (__gcov_dump_int, __gcov_dump); +/* Exported function __gcov_dump. */ + +void +__gcov_dump (void) +{ + __gcov_lock (); + + __gcov_dump_int (); + + __gcov_unlock (); +} #endif /* L_gcov_dump */ #ifdef L_gcov_fork -/* A wrapper for the fork function. Flushes the accumulated profiling data, so - that they are not counted twice. */ +/* A wrapper for the fork function. We reset counters in the child + so that they are not counted twice. */ pid_t __gcov_fork (void) { pid_t pid; - __gcov_flush (); pid = fork (); if (pid == 0) - __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_flush_mx); + { + __GTHREAD_MUTEX_INIT_FUNCTION (&__gcov_mx); + /* We do not need locking as we are the only thread in the child. */ + __gcov_reset_int (); + } return pid; } #endif @@ -194,7 +204,8 @@ __gcov_execl (const char *path, char *arg, ...) unsigned i, length; char **args; - __gcov_flush (); + /* Dump counters only, they will be lost after exec. */ + __gcov_dump (); va_start (ap, arg); va_copy (aq, ap); @@ -210,7 +221,10 @@ __gcov_execl (const char *path, char *arg, ...) args[i] = va_arg (aq, char *); va_end (aq); - return execv (path, args); + int ret = execv (path, args); + /* We reach this code only when execv fails, reset counter then here. */ + __gcov_reset (); + return ret; } #endif @@ -225,7 +239,8 @@ __gcov_execlp (const char *path, char *arg, ...) unsigned i, length; char **args; - __gcov_flush (); + /* Dump counters only, they will be lost after exec. */ + __gcov_dump (); va_start (ap, arg); va_copy (aq, ap); @@ -241,7 +256,10 @@ __gcov_execlp (const char *path, char *arg, ...) args[i] = va_arg (aq, char *); va_end (aq); - return execvp (path, args); + int ret = execvp (path, args); + /* We reach this code only when execv fails, reset counter then here. */ + __gcov_reset (); + return ret; } #endif @@ -257,7 +275,8 @@ __gcov_execle (const char *path, char *arg, ...) char **args; char **envp; - __gcov_flush (); + /* Dump counters only, they will be lost after exec. */ + __gcov_dump (); va_start (ap, arg); va_copy (aq, ap); @@ -274,7 +293,10 @@ __gcov_execle (const char *path, char *arg, ...) envp = va_arg (aq, char **); va_end (aq); - return execve (path, args, envp); + int ret = execve (path, args, envp); + /* We reach this code only when execv fails, reset counter then here. */ + __gcov_reset (); + return ret; } #endif @@ -285,8 +307,12 @@ __gcov_execle (const char *path, char *arg, ...) int __gcov_execv (const char *path, char *const argv[]) { - __gcov_flush (); - return execv (path, argv); + /* Dump counters only, they will be lost after exec. */ + __gcov_dump (); + int ret = execv (path, argv); + /* We reach this code only when execv fails, reset counter then here. */ + __gcov_reset (); + return ret; } #endif @@ -297,8 +323,12 @@ __gcov_execv (const char *path, char *const argv[]) int __gcov_execvp (const char *path, char *const argv[]) { - __gcov_flush (); - return execvp (path, argv); + /* Dump counters only, they will be lost after exec. */ + __gcov_dump (); + int ret = execvp (path, argv); + /* We reach this code only when execv fails, reset counter then here. */ + __gcov_reset (); + return ret; } #endif @@ -309,8 +339,12 @@ __gcov_execvp (const char *path, char *const argv[]) int __gcov_execve (const char *path, char *const argv[], char *const envp[]) { - __gcov_flush (); - return execve (path, argv, envp); + /* Dump counters only, they will be lost after exec. */ + __gcov_dump (); + int ret = execve (path, argv, envp); + /* We reach this code only when execv fails, reset counter then here. */ + __gcov_reset (); + return ret; } #endif #endif /* inhibit_libc */ diff --git a/libgcc/libgcov-merge.c b/libgcc/libgcov-merge.c index c0785b0..1acdaa0 100644 --- a/libgcc/libgcov-merge.c +++ b/libgcc/libgcov-merge.c @@ -86,86 +86,6 @@ __gcov_merge_time_profile (gcov_type *counters, unsigned n_counters) #ifdef L_gcov_merge_topn -/* To merging of TOPN profiles. - counters[0] is the number of executions - for i in 0 ... TOPN-1 - counters[2 * i + 1] is target - counters[2 * i + 2] is corresponding hitrate counter. - - Because we prune counters only those with probability >= 1/TOPN are - present now. - - We use sign of counters[0] to track whether the number of different - targets exceeds TOPN. */ - -static void -merge_topn_values_set (gcov_type *counters) -{ - /* First value is number of total executions of the profiler. */ - gcov_type all = gcov_get_counter (); - gcov_type *total = &counters[0]; - ++counters; - - /* Negative value means that counter is missing some of values. */ - if (all < 0) - *total = -(*total); - - *total += all; - - /* Read all part values. */ - gcov_type read_counters[2 * GCOV_TOPN_VALUES]; - for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++) - { - read_counters[2 * i] = gcov_get_counter_target (); - read_counters[2 * i + 1] = gcov_get_counter_ignore_scaling (-1); - } - - for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++) - { - if (read_counters[2 * i + 1] == 0) - continue; - - unsigned j; - int slot = 0; - - for (j = 0; j < GCOV_TOPN_VALUES; j++) - { - if (counters[2 * j] == read_counters[2 * i]) - { - counters[2 * j + 1] += read_counters[2 * i + 1]; - break; - } - else if (counters[2 * j + 1] < counters[2 * slot + 1]) - slot = j; - } - - if (j == GCOV_TOPN_VALUES) - { - gcov_type slot_count = counters[2 * slot + 1]; - /* We found an empty slot. */ - if (slot_count == 0) - { - /* If we found empty slot, add the value. */ - counters[2 * slot] = read_counters[2 * i]; - counters[2 * slot + 1] = read_counters[2 * i + 1]; - } - else - { - /* Here we are loosing some values. */ - if (*total >= 0) - *total = -(*total); - if (read_counters[2 * i + 1] > slot_count) - { - counters[2 * slot] = read_counters[2 * i]; - counters[2 * slot + 1] = read_counters[2 * i + 1]; - } - else - counters[2 * slot + 1] -= read_counters[2 * i + 1]; - } - } - } -} - /* The profile merging function for choosing the most common value. It is given an array COUNTERS of N_COUNTERS old counters and it reads the same number of counters from the gcov file. The counters @@ -175,13 +95,30 @@ merge_topn_values_set (gcov_type *counters) -- the stored candidate on the most common value of the measured entity -- counter */ + void __gcov_merge_topn (gcov_type *counters, unsigned n_counters) { - gcc_assert (!(n_counters % GCOV_TOPN_VALUES_COUNTERS)); + gcc_assert (!(n_counters % GCOV_TOPN_MEM_COUNTERS)); - for (unsigned i = 0; i < (n_counters / GCOV_TOPN_VALUES_COUNTERS); i++) - merge_topn_values_set (counters + (i * GCOV_TOPN_VALUES_COUNTERS)); + for (unsigned i = 0; i < (n_counters / GCOV_TOPN_MEM_COUNTERS); i++) + { + /* First value is number of total executions of the profiler. */ + gcov_type all = gcov_get_counter_ignore_scaling (-1); + gcov_type n = gcov_get_counter_ignore_scaling (-1); + + counters[GCOV_TOPN_MEM_COUNTERS * i] += all; + + for (unsigned j = 0; j < n; j++) + { + gcov_type value = gcov_get_counter_target (); + gcov_type count = gcov_get_counter_ignore_scaling (-1); + + // TODO: we should use atomic here + gcov_topn_add_value (counters + GCOV_TOPN_MEM_COUNTERS * i, value, + count, 0, 0); + } + } } #endif /* L_gcov_merge_topn */ diff --git a/libgcc/libgcov-profiler.c b/libgcc/libgcov-profiler.c index 6043ac4..45ab93c 100644 --- a/libgcc/libgcov-profiler.c +++ b/libgcc/libgcov-profiler.c @@ -26,17 +26,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "libgcov.h" #if !defined(inhibit_libc) -/* Detect whether target can support atomic update of profilers. */ -#if __SIZEOF_LONG_LONG__ == 4 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 -#define GCOV_SUPPORTS_ATOMIC 1 -#else -#if __SIZEOF_LONG_LONG__ == 8 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 -#define GCOV_SUPPORTS_ATOMIC 1 -#else -#define GCOV_SUPPORTS_ATOMIC 0 -#endif -#endif - #ifdef L_gcov_interval_profiler /* If VALUE is in interval <START, START + STEPS - 1>, then increases the corresponding counter in COUNTERS. If the VALUE is above or below @@ -105,51 +94,13 @@ __gcov_pow2_profiler_atomic (gcov_type *counters, gcov_type value) } #endif - /* Tries to determine N most commons value among its inputs. */ static inline void __gcov_topn_values_profiler_body (gcov_type *counters, gcov_type value, int use_atomic) { - if (use_atomic) - __atomic_fetch_add (&counters[0], 1, __ATOMIC_RELAXED); - else - counters[0]++; - - ++counters; - - /* First try to find an existing value. */ - int empty_counter = -1; - - for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++) - if (value == counters[2 * i]) - { - if (use_atomic) - __atomic_fetch_add (&counters[2 * i + 1], GCOV_TOPN_VALUES, - __ATOMIC_RELAXED); - else - counters[2 * i + 1] += GCOV_TOPN_VALUES; - return; - } - else if (counters[2 * i + 1] <= 0) - empty_counter = i; - - /* Find an empty slot for a new value. */ - if (empty_counter != -1) - { - counters[2 * empty_counter] = value; - counters[2 * empty_counter + 1] = GCOV_TOPN_VALUES; - return; - } - - /* We haven't found an empty slot, then decrement all - counter values by one. */ - for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++) - if (use_atomic) - __atomic_fetch_sub (&counters[2 * i + 1], 1, __ATOMIC_RELAXED); - else - counters[2 * i + 1]--; + gcov_topn_add_value (counters, value, 1, use_atomic, 1); } #ifdef L_gcov_topn_values_profiler diff --git a/libgcc/libgcov-util.c b/libgcc/libgcov-util.c index 449638b..1ada1fe 100644 --- a/libgcc/libgcov-util.c +++ b/libgcc/libgcov-util.c @@ -57,12 +57,12 @@ void gcov_set_verbose (void) #include <ftw.h> #endif -static void tag_function (unsigned, unsigned); -static void tag_blocks (unsigned, unsigned); -static void tag_arcs (unsigned, unsigned); -static void tag_lines (unsigned, unsigned); -static void tag_counters (unsigned, unsigned); -static void tag_summary (unsigned, unsigned); +static void tag_function (unsigned, int); +static void tag_blocks (unsigned, int); +static void tag_arcs (unsigned, int); +static void tag_lines (unsigned, int); +static void tag_counters (unsigned, int); +static void tag_summary (unsigned, int); /* The gcov_info for the first module. */ static struct gcov_info *curr_gcov_info; @@ -80,8 +80,6 @@ static int k_ctrs_mask[GCOV_COUNTERS]; static struct gcov_ctr_info k_ctrs[GCOV_COUNTERS]; /* Number of kind of counters that have been seen. */ static int k_ctrs_types; -/* The object summary being processed. */ -static struct gcov_summary *curr_object_summary; /* Merge functions for counters. */ #define DEF_GCOV_COUNTER(COUNTER, NAME, FN_TYPE) __gcov_merge ## FN_TYPE, @@ -119,7 +117,7 @@ typedef struct tag_format { unsigned tag; char const *name; - void (*proc) (unsigned, unsigned); + void (*proc) (unsigned, int); } tag_format_t; /* Handler table for various Tags. */ @@ -140,7 +138,7 @@ static const tag_format_t tag_table[] = /* Handler for reading function tag. */ static void -tag_function (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED) +tag_function (unsigned tag ATTRIBUTE_UNUSED, int length ATTRIBUTE_UNUSED) { int i; @@ -173,7 +171,7 @@ tag_function (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED) /* Handler for reading block tag. */ static void -tag_blocks (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED) +tag_blocks (unsigned tag ATTRIBUTE_UNUSED, int length ATTRIBUTE_UNUSED) { /* TBD: gcov-tool currently does not handle gcno files. Assert here. */ gcc_unreachable (); @@ -182,7 +180,7 @@ tag_blocks (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED) /* Handler for reading flow arc tag. */ static void -tag_arcs (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED) +tag_arcs (unsigned tag ATTRIBUTE_UNUSED, int length ATTRIBUTE_UNUSED) { /* TBD: gcov-tool currently does not handle gcno files. Assert here. */ gcc_unreachable (); @@ -191,7 +189,7 @@ tag_arcs (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED) /* Handler for reading line tag. */ static void -tag_lines (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED) +tag_lines (unsigned tag ATTRIBUTE_UNUSED, int length ATTRIBUTE_UNUSED) { /* TBD: gcov-tool currently does not handle gcno files. Assert here. */ gcc_unreachable (); @@ -200,9 +198,9 @@ tag_lines (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED) /* Handler for reading counters array tag with value as TAG and length of LENGTH. */ static void -tag_counters (unsigned tag, unsigned length) +tag_counters (unsigned tag, int length) { - unsigned n_counts = GCOV_TAG_COUNTER_NUM (length); + unsigned n_counts = GCOV_TAG_COUNTER_NUM (abs (length)); gcov_type *values; unsigned ix; unsigned tag_ix; @@ -213,20 +211,21 @@ tag_counters (unsigned tag, unsigned length) gcc_assert (k_ctrs[tag_ix].num == 0); k_ctrs[tag_ix].num = n_counts; - k_ctrs[tag_ix].values = values = (gcov_type *) xmalloc (n_counts * sizeof (gcov_type)); + k_ctrs[tag_ix].values = values = (gcov_type *) xcalloc (sizeof (gcov_type), + n_counts); gcc_assert (values); - for (ix = 0; ix != n_counts; ix++) - values[ix] = gcov_read_counter (); + if (length > 0) + for (ix = 0; ix != n_counts; ix++) + values[ix] = gcov_read_counter (); } /* Handler for reading summary tag. */ static void -tag_summary (unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED) +tag_summary (unsigned tag ATTRIBUTE_UNUSED, int ATTRIBUTE_UNUSED) { - curr_object_summary = (gcov_summary *) xcalloc (sizeof (gcov_summary), 1); - gcov_read_summary (curr_object_summary); + gcov_read_summary (&curr_gcov_info->summary); } /* This function is called at the end of reading a gcda file. @@ -243,7 +242,7 @@ read_gcda_finalize (struct gcov_info *obj_info) /* We set the following fields: merge, n_functions, functions and summary. */ obj_info->n_functions = num_fn_info; - obj_info->functions = (const struct gcov_fn_info**) obstack_finish (&fn_info); + obj_info->functions = (struct gcov_fn_info**) obstack_finish (&fn_info); /* wrap all the counter array. */ for (i=0; i< GCOV_COUNTERS; i++) @@ -261,7 +260,7 @@ read_gcda_file (const char *filename) { unsigned tags[4]; unsigned depth = 0; - unsigned magic, version; + unsigned version; struct gcov_info *obj_info; int i; @@ -276,8 +275,7 @@ read_gcda_file (const char *filename) } /* Read magic. */ - magic = gcov_read_unsigned (); - if (magic != GCOV_DATA_MAGIC) + if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC)) { fnotice (stderr, "%s:not a gcov data file\n", filename); gcov_close (); @@ -301,7 +299,6 @@ read_gcda_file (const char *filename) obstack_init (&fn_info); num_fn_info = 0; curr_fn_info = 0; - curr_object_summary = NULL; { size_t len = strlen (filename) + 1; char *str_dup = (char*) xmalloc (len); @@ -325,7 +322,8 @@ read_gcda_file (const char *filename) tag = gcov_read_unsigned (); if (!tag) break; - length = gcov_read_unsigned (); + int read_length = (int)gcov_read_unsigned (); + length = read_length > 0 ? read_length : 0; base = gcov_position (); mask = GCOV_TAG_MASK (tag) >> 1; for (tag_depth = 4; mask; mask >>= 8) @@ -358,7 +356,7 @@ read_gcda_file (const char *filename) { unsigned long actual_length; - (*format->proc) (tag, length); + (*format->proc) (tag, read_length); actual_length = gcov_position () - base; if (actual_length > length) @@ -507,14 +505,58 @@ gcov_get_merge_weight (void) value buffer and weights and then calls the merge function. */ static void -merge_wrapper (gcov_merge_fn f, gcov_type *v1, gcov_unsigned_t n, - gcov_type *v2, unsigned w) +merge_wrapper (gcov_merge_fn f, gcov_type *v1, gcov_unsigned_t n1, + gcov_type *v2, gcov_unsigned_t n2, unsigned w) { gcov_value_buf = v2; gcov_value_buf_pos = 0; - gcov_value_buf_size = n; + gcov_value_buf_size = n2; gcov_merge_weight = w; - (*f) (v1, n); + (*f) (v1, n1); +} + +/* Convert on disk representation of a TOPN counter to in memory representation + that is expected from __gcov_merge_topn function. */ + +static void +topn_to_memory_representation (struct gcov_ctr_info *info) +{ + auto_vec<gcov_type> output; + gcov_type *values = info->values; + int count = info->num; + + while (count > 0) + { + output.safe_push (values[0]); + gcov_type n = values[1]; + output.safe_push (n); + if (n > 0) + { + struct gcov_kvp *tuples + = (struct gcov_kvp *)xcalloc (sizeof (struct gcov_kvp), n); + for (unsigned i = 0; i < n - 1; i++) + tuples[i].next = &tuples[i + 1]; + for (unsigned i = 0; i < n; i++) + { + tuples[i].value = values[2 + 2 * i]; + tuples[i].count = values[2 + 2 * i + 1]; + } + output.safe_push ((intptr_t)&tuples[0]); + } + else + output.safe_push (0); + + unsigned len = 2 * n + 2; + values += len; + count -= len; + } + gcc_assert (count == 0); + + /* Allocate new buffer and copy it there. */ + info->num = output.length (); + info->values = (gcov_type *)xmalloc (sizeof (gcov_type) * info->num); + for (unsigned i = 0; i < info->num; i++) + info->values[i] = output[i]; } /* Offline tool to manipulate profile data. @@ -541,12 +583,17 @@ gcov_merge (struct gcov_info *info1, struct gcov_info *info2, int w) int has_mismatch = 0; gcc_assert (info2->n_functions == n_functions); + + /* Merge summary. */ + info1->summary.runs += info2->summary.runs; + info1->summary.sum_max += info2->summary.sum_max; + for (f_ix = 0; f_ix < n_functions; f_ix++) { unsigned t_ix; - const struct gcov_fn_info *gfi_ptr1 = info1->functions[f_ix]; - const struct gcov_fn_info *gfi_ptr2 = info2->functions[f_ix]; - const struct gcov_ctr_info *ci_ptr1, *ci_ptr2; + struct gcov_fn_info *gfi_ptr1 = info1->functions[f_ix]; + struct gcov_fn_info *gfi_ptr2 = info2->functions[f_ix]; + struct gcov_ctr_info *ci_ptr1, *ci_ptr2; if (!gfi_ptr1 || gfi_ptr1->key != info1) continue; @@ -570,8 +617,14 @@ gcov_merge (struct gcov_info *info1, struct gcov_info *info2, int w) gcc_assert (merge1 == merge2); if (!merge1) continue; - gcc_assert (ci_ptr1->num == ci_ptr2->num); - merge_wrapper (merge1, ci_ptr1->values, ci_ptr1->num, ci_ptr2->values, w); + + if (merge1 == __gcov_merge_topn) + topn_to_memory_representation (ci_ptr1); + else + gcc_assert (ci_ptr1->num == ci_ptr2->num); + + merge_wrapper (merge1, ci_ptr1->values, ci_ptr1->num, + ci_ptr2->values, ci_ptr2->num, w); ci_ptr1++; ci_ptr2++; } diff --git a/libgcc/libgcov.h b/libgcc/libgcov.h index 023293e..81e1895 100644 --- a/libgcc/libgcov.h +++ b/libgcc/libgcov.h @@ -85,6 +85,19 @@ typedef unsigned gcov_type_unsigned __attribute__ ((mode (QI))); #define GCOV_LOCKED 0 #endif +#ifndef GCOV_SUPPORTS_ATOMIC +/* Detect whether target can support atomic update of profilers. */ +#if __SIZEOF_LONG_LONG__ == 4 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 +#define GCOV_SUPPORTS_ATOMIC 1 +#else +#if __SIZEOF_LONG_LONG__ == 8 && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 +#define GCOV_SUPPORTS_ATOMIC 1 +#else +#define GCOV_SUPPORTS_ATOMIC 0 +#endif +#endif +#endif + /* In libgcov we need these functions to be extern, so prefix them with __gcov. In libgcov they must also be hidden so that the instance in the executable is not also used in a DSO. */ @@ -147,7 +160,7 @@ extern struct gcov_info *gcov_list; /* Poison these, so they don't accidentally slip in. */ #pragma GCC poison gcov_write_string gcov_write_tag gcov_write_length -#pragma GCC poison gcov_time gcov_magic +#pragma GCC poison gcov_time #ifdef HAVE_GAS_HIDDEN #define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) @@ -203,7 +216,8 @@ struct gcov_info const struct gcov_fn_info *const *functions; /* pointer to pointers to function information */ #else - const struct gcov_fn_info **functions; + struct gcov_fn_info **functions; + struct gcov_summary summary; #endif /* !IN_GCOV_TOOL */ }; @@ -253,6 +267,12 @@ extern void __gcov_reset_int (void) ATTRIBUTE_HIDDEN; /* User function to enable early write of profile information so far. */ extern void __gcov_dump_int (void) ATTRIBUTE_HIDDEN; +/* Lock critical section for __gcov_dump and __gcov_reset functions. */ +extern void __gcov_lock (void) ATTRIBUTE_HIDDEN; + +/* Unlock critical section for __gcov_dump and __gcov_reset functions. */ +extern void __gcov_unlock (void) ATTRIBUTE_HIDDEN; + /* The merge function that just sums the counters. */ extern void __gcov_merge_add (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; @@ -367,6 +387,103 @@ gcov_get_counter_target (void) #endif } +/* Add VALUE to *COUNTER and make it with atomic operation + if USE_ATOMIC is true. */ + +static inline void +gcov_counter_add (gcov_type *counter, gcov_type value, + int use_atomic ATTRIBUTE_UNUSED) +{ +#if GCOV_SUPPORTS_ATOMIC + if (use_atomic) + __atomic_fetch_add (counter, value, __ATOMIC_RELAXED); + else +#endif + *counter += value; +} + +/* Add key value pair VALUE:COUNT to a top N COUNTERS. When INCREMENT_TOTAL + is true, add COUNT to total of the TOP counter. If USE_ATOMIC is true, + do it in atomic way. */ + +static inline void +gcov_topn_add_value (gcov_type *counters, gcov_type value, gcov_type count, + int use_atomic, int increment_total) +{ + if (increment_total) + gcov_counter_add (&counters[0], 1, use_atomic); + + struct gcov_kvp *prev_node = NULL; + struct gcov_kvp *minimal_node = NULL; + struct gcov_kvp *current_node = (struct gcov_kvp *)(intptr_t)counters[2]; + + while (current_node) + { + if (current_node->value == value) + { + gcov_counter_add (¤t_node->count, count, use_atomic); + return; + } + + if (minimal_node == NULL + || current_node->count < minimal_node->count) + minimal_node = current_node; + + prev_node = current_node; + current_node = current_node->next; + } + + if (counters[1] == GCOV_TOPN_MAXIMUM_TRACKED_VALUES) + { + if (--minimal_node->count < count) + { + minimal_node->value = value; + minimal_node->count = count; + } + } + else + { + struct gcov_kvp *new_node + = (struct gcov_kvp *)xcalloc (1, sizeof (struct gcov_kvp)); + new_node->value = value; + new_node->count = count; + + int success = 0; + if (!counters[2]) + { +#if GCOV_SUPPORTS_ATOMIC + if (use_atomic) + { + struct gcov_kvp **ptr = (struct gcov_kvp **)(intptr_t)&counters[2]; + success = !__sync_val_compare_and_swap (ptr, 0, new_node); + } + else +#endif + { + counters[2] = (intptr_t)new_node; + success = 1; + } + } + else if (prev_node && !prev_node->next) + { +#if GCOV_SUPPORTS_ATOMIC + if (use_atomic) + success = !__sync_val_compare_and_swap (&prev_node->next, 0, + new_node); + else +#endif + { + prev_node->next = new_node; + success = 1; + } + } + + /* Increment number of nodes. */ + if (success) + gcov_counter_add (&counters[1], 1, use_atomic); + } +} + #endif /* !inhibit_libc */ #endif /* GCC_LIBGCOV_H */ |